Android 狀態列、底部導航欄的那些事
1. 需求
平常專案中,對頂部狀態列Status Bar,以及底部導航欄Navigation Bar的操作場景一般可以概括為以下幾個場景:
- 隱藏狀態列,導航欄,使用者互動時(點選或滑動螢幕)出現(或不出現)。如歡迎、登入、全屏視訊播放、閱讀等介面使用。
- 透明狀態列,圖片或佈局延伸到狀態列
- 狀態列字型預設為白色,部分 app 修改為黑色
- 變色狀態列,修改狀態列背景顏色
2. 相關API
我們沿著Android API的發展時間從頭來說
- API 1
//4.4 上,頂部下滑,出現半透明狀態列,過一會兒狀態列消失 //4.1 上,頂部下滑,沒反應 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
效果和通過主題樣式的方式在styles.xml檔案中設定屬性android:windowFullscreen
是一樣的,都是通過設定window的屬性來影響視窗上修飾控制元件的顯示
- Android3.0
在Android3.0中,View添加了一個重要的方法:View.setSystemUiVisibility(int),通過視窗根View(DecorView)提供的方法來直接控制其上的視窗裝飾元素System UI的顯示和隱藏,並添加了
- View.STATUS_BAR_VISIBLE
- View.STATUS_BAR_HIDDEN :實測statusbar不會消失,僅隱藏statusbar 部分內容
兩個Flag用於控制Status Bar的顯示與隱藏。
一般是這麼用的:
View decorView = getWindow().getDecorView(); int uiOptions =View.STATUS_BAR_VISIBLE; decorView.setSystemUiVisibility(uiOptions);
- Android4.0
-
View.STATUS_BAR_VISIBLE 改為 View.SYSTEM_UI_FLAG_VISIBLE
-
View.STATUS_BAR_HIDDEN 更名為 View.SYSTEM_UI_FLAG_LOW_PROFILE,該 flag 同時影響 StatusBar 和 NavigationBar ,但並不會使得 SystemUI 消失,而只會使得背景很淺,並且去掉 SystemUI 的一些圖示或文字。
另外添加了一個flag:SYSTEM_UI_FLAG_HIDE_NAVIGATION,會隱藏NavigationBar,但是由於NavigationBar是非常重要的,因此只要有使用者互動(例如點選螢幕),系統就會清除這個flag使NavigationBar就會再次出現。
- Android 4.1
-
View.SYSTEM_UI_FLAG_FULLSCREEN: 這個標誌與WindowManager.LayoutParams.FLAG_FULLSCREEN作用相同(全屏佈局且隱藏狀態列)
—— 4.1 上頂部下滑沒反應
—— 4.4 上頂部下滑從新出現狀態列,且擠壓 Activity 的佈局。
-
View.SYSTEM_UI_FLAG_LAYOUT_STABLE: 與其它flag配合使用,防止系統欄隱藏時內容區域發生變化。
-
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: Activity全屏顯示,但狀態列不會被隱藏覆蓋,狀態列依然可見,Activity頂端佈局部分會被狀態遮住
-
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: 使內容佈局到NavigationBar之下。
- Android 4.4
- View.SYSTEM_UI_FLAG_IMMERSIVE
該標誌是SYSTEM_UI_FLAG_HIDE_NAVIGATION修飾符,也只有和它結合使用時才有效果,並且它只有一個作用,單獨使用 SYSTEM_UI_FLAG_HIDE_NAVIGATION ,導航欄消失,不過系統將在任何使用者互動時強制清除SYSTEM_UI_FLAG_HIDE_NAVIGATION,導航欄會再次出現。新增 View.SYSTEM_UI_FLAG_IMMERSIVE 後,互動時導航欄不會出現,但如果底部向上滑動時,導航欄仍會出現。
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
使用此標誌建立沉浸式體驗,它是SYSTEM_UI_FLAG_FULLSCREEN和SYSTEM_UI_FLAG_HIDE_NAVIGATION的修飾符,因此只有與其中一個或兩個標誌組合使用時才會產生效果。
該標誌和 View.SYSTEM_UI_FLAG_FULLSCREEN 配合使用:狀態列隱藏在沉浸模式下,但可以通過系統手勢暫時顯示出來,比如從螢幕頂部滑動。這些暫時的系統欄將覆蓋應用程式的內容,可能有一定程度的透明度,並會在短時間後自動隱藏。
該標誌和 SYSTEM_UI_FLAG_HIDE_NAVIGATION 配合使用:導航欄隱藏在沉浸模式下,底部向上滑動出現,過一段時間自動隱藏。
- FLAG_TRANSLUCENT_STATUS
這個屬於Window flag,當使用這個flag時SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN會被自動新增,同時,設定FLAG_TRANSLUCENT_STATUS也會影響到StatusBar的背景色,但並沒有固定的表現:
—— 對於7.0以上的機型,設定此flage會使得StatusBar半透明
—— 對於6.0以上的機型,設定此flage會使得StatusBar完全透明
—— 對於5.x的機型,大部分是使背景色半透明,小米和魅族以及其它少數機型會全透明
—— 對於4.4的機型,小米和魅族是透明色,而其它系統上就只是黑色到透明色的漸變。
- FLAG_TRANSLUCENT_NAVIGATION
當使用這這個flag時SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION會被自動新增。同時,設定FLAG_TRANSLUCENT_STATUS也會影響到 NavigationBar 的背景色,效果與 FLAG_TRANSLUCENT_STATUS 相同。
- Android 5.0
-
主題裡通過colorPrimaryDark來指定 StatusBar 背景色
-
可以呼叫 window.setStatusBarColor(@ColorInt int color) 來修改狀態列顏色,但是讓這個方法生效有一個前提條件:你必須給window新增FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS並且取消FLAG_TRANSLUCENT_STATUS
- Android 6.0
在Android6以後,我們只要給SystemUI加上SYSTEM_UI_FLAG_LIGHT_STATUS_BAR這個flag,就可以讓字型和圖示變為黑色。