安卓狀態列適配技巧
背景
公司長期以來只有一套UI稿,而且是按照iOS標準來設計的,狀態列效果自然是白底黑字。無奈啊,不過沒辦法,所以想著怎麼也得適配一下。經過調研後得知:Android5.0以上系統版本可以修改狀態列顏色,但是隻有部分小米的MIUI、魅族的Flyme和Android6.0以上系統可以把狀態列文字和圖示換成深色,其他的系統狀態列文字預設都是白色的,換成淺色背景的話字型和圖示就看不到;所以我們適配的前提是系統能將狀態列字型設定成深(黑)色。
我司App適配後效果對比
before | after |
---|---|
![]() image |
![]() image |
![]() image |
![]() image |
適配方案
狀態列淺色背景(比如白底黑字)
- 安卓版本6.0及以上直接使用系統api,style裡面配置。
- 系統版本在4.4和6.0之間,特殊處理MIUI6+和Flyme4+;
- 沉浸式和全屏模式需單獨處理。
- 其它情況不處理。(系統預設深色背景+白色字型。)
狀態列深色背景(能明顯看到狀態列白色字型)
由於系統狀態列上字型預設就是白色的,只需更改背景色就能完成適配。
- 系統版本5.0及以上使用系統API設定狀態列顏色。
- 系統版本為4.4,使用 WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS 屬性,偽造一個狀態列高度的view並設定其背景色。
- 沉浸式和全屏模式需單獨處理。
程式碼實現
下面程式碼就以狀態列淺色背景為例作簡單示範;狀態列為深色背景時較簡單,讀者可根據文末提供的程式碼參考,自行完成適配。
- 普通頁面適配(邏輯建議放在BaseActivity中,特殊頁面覆蓋其方法實現即可)
// BaseActivity中定義方法 /** * 配置沉浸式模式 */ protected void configImmersiveMode(){ ImmersiveModeUtil.setDefaultImmersiveMode(this); } // ImmersiveModeUtil 工具類 /** * App預設的沉浸式預設 * * @param activity */ public static void setDefaultImmersiveMode(@NonNull Activity activity) { // 設定狀態列和darkMode,如果設定成功,則設定狀態列背景為白色即可。 final boolean darkMode = setStatusBarDarkMode(activity, true); if (darkMode) { setStatusBarBgColor(activity, Color.WHITE); } } /** * 先判斷MIUI系統,然後Flyme,最後主流系統 * * @param activity * @param isFontColorDark 深色字型(Light)模式 * @return 是否設定成功 */ @TargetApi(Build.VERSION_CODES.M) public static boolean setStatusBarDarkMode(@NonNull Activity activity, boolean isFontColorDark) { boolean result = setMIUIStatusBarDarkIcon(activity, isFontColorDark); if (!result) { result = setMeizuStatusBarDarkIcon(activity, isFontColorDark); if (!result) { result = setCommonStatusBarDarkMode(activity, isFontColorDark); } } if (result) { currentStatusBarStyle = isFontColorDark ? 2 : 1; } return result; }
以上程式碼,重點在於setStatusBarDarkMode()方法邏輯。先解釋下引數 isFontColorDark 的意思, true表示狀態列中字型和icon顯示為深色(黑色),false則顯示成白色 (也就是系統預設樣式)。這裡可以看到, 在setStatusBarDarkMode()方法中,先設定MIUI系統,如果失敗,繼續設定魅族系統,如果又失敗,就呼叫6.0以上官方API;其中任何一個方法成功則直接返回。 再看setDefaultImmersiveMode()方法,只有在設定darkMode返回成功的情況下才設定狀態列背景為白色;換句話說,如果系統不支援darkMode,則放棄適配。
- 狀態列背景全透明、沉浸式和全屏模式等處理
這種情況只需呼叫setSystemUiVisibility()方法就能搞定,狀態列背景設定官方5.0也有api支援,4.4系統可新增 WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS亦能實現。
這裡就不貼程式碼了,具體可參看文末提供的demo工程程式碼。
注意點:
- 如果內容區域為全屏(顯示到狀態列下面),建議使用paddingTop一個狀態列高度的view來實現。如果介面中沒有輸入框,也可使用
android:fitsSystemWindows="true"
屬性適配。
全屏模式下的問題及解決辦法
- 問題1:顯示對話方塊導致狀態列或虛擬導航欄UI異常
- 辦法1:dialog顯示前設定FLAG_NOT_FOCUSABLE,顯示後清除改標識。
- 辦法2:監聽Dialog的onDismiss事件,重新恢復全屏。
參考: ofollow,noindex">how-do-i-maintain-the-immersive-mode-in-dialogs
- 問題2:全屏模式下,輸入框彈出時,ajustResize無效
參考: android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible
demo原始碼已上傳github ,如果對你有幫助,歡迎star~