Android 狀態(tài)欄、底部導(dǎo)航欄的那些事

1. 需求

平常項(xiàng)目中,對(duì)頂部狀態(tài)欄Status Bar,以及底部導(dǎo)航欄Navigation Bar的操作一般可以概括為以下幾個(gè)場(chǎng)景:

  • 隱藏狀態(tài)欄,導(dǎo)航欄,用戶交互時(shí)(點(diǎn)擊或滑動(dòng)屏幕)出現(xiàn)(或不出現(xiàn))。如歡迎、登錄、全屏視頻播放、閱讀等界面使用。
  • 透明狀態(tài)欄,圖片或布局延伸到狀態(tài)欄
  • 狀態(tài)欄字體默認(rèn)為白色,部分 app 修改為黑色
  • 變色狀態(tài)欄,修改狀態(tài)欄背景顏色

2. 相關(guān)API

我們沿著Android API的發(fā)展時(shí)間從頭來(lái)說(shuō),另外,建議多看源碼,這塊內(nèi)容,在源碼注釋里寫(xiě)的非常清楚

1. API 1
  • FLAG_FULLSCREEN

在Android 3.0及以前,StatusBar只能顯示與隱藏,即全屏模式,通過(guò)WindowManager.LayoutParams.FLAG_FULLSCREEN來(lái)實(shí)現(xiàn):

// 全屏布局且隱藏狀態(tài)欄:
//4.4 上,頂部下滑,出現(xiàn)半透明狀態(tài)欄,過(guò)一會(huì)兒狀態(tài)欄消失
//4.1 上,頂部下滑,沒(méi)反應(yīng)
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

效果和通過(guò)主題樣式的方式在styles.xml文件中設(shè)置屬性android:windowFullscreen 是一樣的,都是通過(guò)設(shè)置window的屬性來(lái)影響窗口上修飾控件的顯示

2. Android3.0 (API 11)

在Android3.0中,View添加了一個(gè)重要的方法:View.setSystemUiVisibility(int),用于控制包括Status Bar在內(nèi)的一些窗口裝飾元素的顯示,通過(guò)窗口根View(DecorView)提供的方法來(lái)直接控制其上的窗口裝飾元素System UI的顯示和隱藏,并添加了

  • View.STATUS_BAR_VISIBLE
  • View.STATUS_BAR_HIDDEN :實(shí)測(cè)statusbar不會(huì)消失,僅隱藏statusbar 部分內(nèi)容

兩個(gè)Flag用于控制Status Bar的顯示與隱藏,不過(guò)在4.0(API 14)中就廢棄了。
一般是這么用的:

 View decorView = getWindow().getDecorView();
 int uiOptions =  View.STATUS_BAR_VISIBLE;
 decorView.setSystemUiVisibility(uiOptions);
3. Android4.0 (API 14)

在4.0(API 14)中,Andorid引入了Navigation Bar,并相應(yīng)添加了一個(gè)flag:

  • SYSTEM_UI_FLAG_HIDE_NAVIGATION
    用來(lái)控制NavigationBar的顯示,但是由于NavigationBar是非常重要的,因此只要有用戶交互(例如點(diǎn)擊屏幕),系統(tǒng)就會(huì)清除這個(gè)flag使NavigationBar就會(huì)再次出現(xiàn)。

  • View.STATUS_BAR_VISIBLE 改為 View.SYSTEM_UI_FLAG_VISIBLE

  • View.STATUS_BAR_HIDDEN 更名為 View.SYSTEM_UI_FLAG_LOW_PROFILE,該 flag 會(huì)同時(shí)影響 StatusBar 和 NavigationBar ,但不會(huì)使Status Bar和Navigation Bar消失,而是會(huì)使它們變暗,降低它們對(duì)視覺(jué)的干擾,使用戶可以專(zhuān)注于應(yīng)用的內(nèi)容,但仍可響應(yīng)用戶的交互,當(dāng)和它們的交互發(fā)生時(shí),會(huì)退出Low Profile的狀態(tài)。

4. Android 4.1 (API 16)

在4.1(API 16)中,對(duì)Status Bar和Navigation Bar的控制進(jìn)一步增強(qiáng)。

  • View.SYSTEM_UI_FLAG_FULLSCREEN: 這個(gè)標(biāo)志與WindowManager.LayoutParams.FLAG_FULLSCREEN有相同的視覺(jué)效果(全屏布局且隱藏狀態(tài)欄),但在系統(tǒng)手勢(shì)交互后兩者在4.4以上有不同表現(xiàn)
    —— 4.1 上頂部下滑沒(méi)反應(yīng)
    —— 4.4 上頂部下滑重新出現(xiàn)狀態(tài)欄,不透明,且擠壓 Activity 的布局。
  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: Activity全屏顯示,但狀態(tài)欄不會(huì)被隱藏覆蓋,狀態(tài)欄依然可見(jiàn),Activity頂端布局部分會(huì)被狀態(tài)遮住。此flag與透明狀態(tài)欄一起使用,就可以實(shí)現(xiàn)現(xiàn)在不少app實(shí)現(xiàn)的狀態(tài)欄透明,圖片或布局延伸到狀態(tài)欄的效果了,不過(guò)這塊需要針對(duì)不同API級(jí)別進(jìn)行適配,主要因?yàn)闋顟B(tài)欄透明在不同的API上顯示不盡相同。

  • View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: 使內(nèi)容布局到NavigationBar之下。

  • View.SYSTEM_UI_FLAG_LAYOUT_STABLE: 在使用View.SYSTEM_UI_FLAG_FULLSCREEN|View.SYSTEM_UI_FLAG_HIDE_NAVIGATION時(shí),Status Bar和Navigation Bar都會(huì)隱藏,Activity的UI占據(jù)整個(gè)屏幕,當(dāng)System UI再次顯示時(shí),應(yīng)用程序窗口會(huì)被重新Resize和Layout,為System UI騰出空間。而這個(gè)標(biāo)簽就是解決這個(gè)問(wèn)題,它需要與上面提到的兩個(gè)layout的flag配合使用,控制當(dāng)Status Bar或Navigation Bar顯示或隱藏時(shí),Activity的UI是被重新Resize和Layout,防止因系統(tǒng)欄的顯示和隱藏導(dǎo)致內(nèi)容區(qū)域發(fā)生變化。

5. Android 4.4 (API 19)

由于對(duì)Status Bar,和Navigation Bar 都是很重要的功能,尤其是Navigation Bar,對(duì)于只有虛擬按鍵的手機(jī),如果隱藏掉Navigation Bar,連切換程序都做不到,所以,當(dāng)用戶和手機(jī)有任何交互的時(shí)候都會(huì)強(qiáng)制清除掉隱藏狀態(tài)欄和導(dǎo)航欄的flag,重新顯示Status Bar和Navigation Bar,而且不會(huì)再次隱藏消失,一些情況下這可能就不是我們想要的效果,比如讀書(shū),看視頻,所以在4.4(API 19)中引入了沉浸模式。

  • View.SYSTEM_UI_FLAG_IMMERSIVE

該標(biāo)志是SYSTEM_UI_FLAG_HIDE_NAVIGATION修飾符,也只有和它結(jié)合使用時(shí)才有效果,并且它只有一個(gè)作用,單獨(dú)使用 SYSTEM_UI_FLAG_HIDE_NAVIGATION ,導(dǎo)航欄消失,不過(guò)系統(tǒng)將在任何用戶交互時(shí)強(qiáng)制清除SYSTEM_UI_FLAG_HIDE_NAVIGATION,導(dǎo)航欄再次出現(xiàn)。添加 View.SYSTEM_UI_FLAG_IMMERSIVE 后,普通交互時(shí)導(dǎo)航欄不會(huì)出現(xiàn),只有在系統(tǒng)交付手勢(shì)時(shí)(如底部向上滑動(dòng)時(shí)),導(dǎo)航欄才會(huì)出現(xiàn),不過(guò)也不會(huì)再次隱藏。

  • View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY

使用此標(biāo)志創(chuàng)建沉浸式體驗(yàn),它是SYSTEM_UI_FLAG_FULLSCREEN和SYSTEM_UI_FLAG_HIDE_NAVIGATION的修飾符,因此只有與其中一個(gè)或兩個(gè)標(biāo)志組合使用時(shí)才會(huì)產(chǎn)生效果。該標(biāo)志和View.SYSTEM_UI_FLAG_IMMERSIVE的不同之處在于當(dāng)用戶在系統(tǒng)手勢(shì)操作后,狀態(tài)欄或?qū)Ш綑诔霈F(xiàn),但短時(shí)間后會(huì)自動(dòng)再次隱藏。

該標(biāo)志和 View.SYSTEM_UI_FLAG_FULLSCREEN 配合使用:狀態(tài)欄隱藏在沉浸模式下,但可以通過(guò)系統(tǒng)手勢(shì)暫時(shí)顯示出來(lái),比如從屏幕頂部滑動(dòng)。這些暫時(shí)的系統(tǒng)欄將覆蓋應(yīng)用程序的內(nèi)容,可能有一定程度的透明度,并會(huì)在短時(shí)間后自動(dòng)隱藏。

該標(biāo)志和 SYSTEM_UI_FLAG_HIDE_NAVIGATION 配合使用:導(dǎo)航欄隱藏在沉浸模式下,底部向上滑動(dòng)出現(xiàn),過(guò)一段時(shí)間自動(dòng)隱藏。

除了控制System UI的顯示和隱藏外,還可以使它們變成透明的,在4.4(API 19)中還引入了

  • FLAG_TRANSLUCENT_STATUS

這個(gè)屬于Window flag,也可以在主題中設(shè)置android: windowTranslucentStatus設(shè)置該屬性,當(dāng)使用這個(gè)flag時(shí)SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN會(huì)被自動(dòng)添加,同時(shí),設(shè)置FLAG_TRANSLUCENT_STATUS也會(huì)影響到StatusBar的背景色,但并沒(méi)有固定的表現(xiàn):

—— 對(duì)于7.0以上的機(jī)型,設(shè)置此flage會(huì)使得StatusBar半透明
—— 對(duì)于6.0以上的機(jī)型,設(shè)置此flage會(huì)使得StatusBar完全透明
—— 對(duì)于5.x的機(jī)型,大部分是使背景色半透明,小米和魅族以及其它少數(shù)機(jī)型會(huì)全透明
—— 對(duì)于4.4的機(jī)型,小米和魅族是透明色,而其它系統(tǒng)上就只是黑色到透明色的漸變。

  • FLAG_TRANSLUCENT_NAVIGATION

Window flag,也可以在主題中設(shè)置android: windowTranslucentNavigation設(shè)置該屬性,當(dāng)使用這這個(gè)flag時(shí)SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION會(huì)被自動(dòng)添加。同時(shí),設(shè)置FLAG_TRANSLUCENT_STATUS也會(huì)影響到 NavigationBar 的背景色,效果與 FLAG_TRANSLUCENT_STATUS 相同。

6. Android 5.0
  • 主題里通過(guò)colorPrimaryDark來(lái)指定 StatusBar 背景色

  • 可以調(diào)用 window.setStatusBarColor(@ColorInt int color) 來(lái)修改狀態(tài)欄顏色,但是讓這個(gè)方法生效有一個(gè)前提條件:你必須給window添加FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS并且取消FLAG_TRANSLUCENT_STATUS

7. Android 6.0

在Android6以后,我們只要給SystemUI加上SYSTEM_UI_FLAG_LIGHT_STATUS_BAR這個(gè)flag,就可以讓字體和圖標(biāo)變?yōu)楹谏?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容