何謂沉浸式狀態(tài)欄##
說白了兵睛,沉浸式狀態(tài)欄本質(zhì)上就是給系統(tǒng)狀態(tài)欄著色挚币。當這個顏色和我們Activity
中的ToolBar
或者ActionBar
所使用的背景顏色一致時就會有沉浸式的效果苛吱。
怎么給狀態(tài)欄著色##
那么我們要怎么樣才能給系統(tǒng)狀態(tài)欄著色呢?谷歌后知后覺碧聪,終于在API 21
的Window
類中添加了相應(yīng)的方法,方法聲明如下:
public abstract class Window {
/**
For this to take effect,the window must be drawing the system bar backgrounds with
android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS and
android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS must not be set
**/
public abstract void setStatusColor(int color)筐乳;
}
具體的實現(xiàn)在PhoneWindow
類中歌殃,這里不再深入。既然方法都有了蝙云,那么直接調(diào)用就行了氓皱。這里我們在Activity
中將狀態(tài)欄顏色設(shè)置為紅色:
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.parseColor("#FF0000"));
注意,上面的代碼假設(shè)當前系統(tǒng)API Level >= 21
勃刨,因為只有滿足條件的SDK版本才能找到該方法波材;與此同時,在設(shè)置狀態(tài)欄顏色的同時朵你,API文檔 告訴我們還需要同步設(shè)置WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
這個Window Flag
各聘,并且需要保證WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
這個Window Flag
沒有被設(shè)置。否則抡医,不會生效躲因。
在調(diào)用任何一個不熟悉的方法時,請首先仔細閱讀一下API 文檔
上面忌傻,我們通過方法調(diào)用給系統(tǒng)狀態(tài)欄著色大脉;當然也可以通過指定Theme
來完成;
<style name="MaterialAppTheme" parent="android:Theme.Material.Light">
<item name="android:colorPrimaryDark">#FF0000</item>
<item name="android:statusBarColor">#00FF00</item>
</style>
從Material Theme
中繼承水孩,覆寫android:statusBarColor
屬性镰矿,指定具體顏色值即可。Material Theme
中android:statusBarColor
屬性的值默認使用android:colorPrimaryDark
屬性指定的值俘种;所以我們也可以僅僅指定android:colorPrimaryDark
屬性秤标;
如果因為某種原因,不從Material Theme
中繼承宙刘,那么就只能老老實實地指定特定的屬性不能偷懶苍姜,這些屬性包括android:statusBarColor
,android:windowDrawsSystemBarBackgrounds
悬包。
<style name="CustomAppTheme" parent="android:Theme.Light">
<item name="android:statusBarColor">#00FF00</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
這里衙猪,我們只從Theme.Light
中繼承,那就不要指望它能像Material Theme
那樣幫我們做一些事布近;android:statusBarColor
必須指定垫释,因為它不再有默認的指向android:colorPrimaryDark
;此外撑瞧,android:windowDrawsSystemBarBackgrounds
為true
必不可少棵譬;就像上面使用setStatusColor
方法時需要注意的那樣,這個屬性相當于添加了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
(當然你也可以不在Theme
中指定這個屬性预伺,使用如上代碼那種方式添加Window Flag
)茫船;而從Material Theme
中繼承時沒有那樣做琅束,是因為Material Theme
中它默認值為true
。
注意算谈,上面Theme
的聲明,對應(yīng)的資源文件應(yīng)該在values-v21
文件夾下料滥。因為不管是相應(yīng)的屬性然眼,還是對應(yīng)的Material Theme
都是至少API 21
才能使用的。
兼容低版本
OK葵腹,到此為止高每,我們所討論的都是基于API 21
以上的。如果低版本該怎么辦践宴?低版本的系統(tǒng)是不支持給狀態(tài)欄著色的鲸匿,但卻可以通過 透明狀態(tài)欄+透明背景顏色 來實現(xiàn)相同的效果;廢話不多說阻肩,來看實現(xiàn)带欢。
將系統(tǒng)狀態(tài)欄設(shè)置為透明
這是第一步】揪可以通過代碼方式
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
或者Theme Attribute
的方式
<item name="android:windowTranslucentStatus">true</item>
設(shè)置對應(yīng)背景顏色
接下來乔煞,就是背景顏色的設(shè)置。首先需要將ActionBar
或者ToolBar
的背景顏色設(shè)置為我們需要的顏色柒室,具體如何設(shè)置不再深入渡贾,請自行研究(這里,如果沒有使用到ActionBar
或者ToolBar
雄右,這一步可直接略過)空骚。
其次,設(shè)置Activity
根布局的背景顏色為一致的顏色擂仍;Just a piece of cake!
最后囤屹,我們還需要做一個調(diào)整。當設(shè)置了狀態(tài)欄為透明后防楷,Activity
會相當于一個FullScreen
的全屏設(shè)置牺丙,窗口會占滿整個屏幕,整體的內(nèi)容會往上移動一段狀態(tài)欄高度的距離复局,這樣就會導(dǎo)致狀態(tài)欄覆蓋到我們的內(nèi)容冲簿。這時,我們需要在根布局上設(shè)置android:fitsSystemWindows="true"
亿昏,這樣系統(tǒng)會幫我們重新調(diào)整窗口的位置避免出現(xiàn)覆蓋的情況(無非就是給我們的窗口加上一個padding值)峦剔;
注意,上面透明欄+背景色
的方式只適用于API 19
以上角钩,因為這個版本以上的系統(tǒng)才支持透明化狀態(tài)欄吝沫,所以呻澜,19
以下的系統(tǒng)不支持沉浸式狀態(tài)欄
其實系統(tǒng)的導(dǎo)航欄在
API 19
以上同狀態(tài)欄一樣也支持透明化和設(shè)置背景顏色,但這不是本文內(nèi)容
關(guān)于透明化狀態(tài)欄
上面說到android:windowTranslucentStatus
可用于API 19以上的版本透明化狀態(tài)欄惨险;但請注意羹幸,在19版本和19版本以上該屬性生效時存在差異。具體表現(xiàn)如下(這里盜用stackoverflow
上的一張圖說明)
上圖中辫愉,左邊為19版本的顯示效果栅受,右邊為21版本的效果;我們可以從圖中看到比較明顯的差異恭朗。在19版本中屏镊,系統(tǒng)給SystemBar
添加了一個漸變,而21版本的則是一個透明的純色痰腮。如果我們使用android:windowTranslucentStatus
在21版本及以上來實現(xiàn)沉浸式的應(yīng)用而芥,則最終效果將不會太理想;那么是不是就不能實現(xiàn)了呢膀值?No棍丐!
21版本以上的透明系統(tǒng)欄需要使用android:statusBarColor = "@android:color/transparent"
來實現(xiàn);這里android:windowTranslucentStatus
肯定是為false
的虫腋,因為這兩個屬性是不能同時生效的骄酗。但是由于android:windowTranslucentStatus
屬性的禁用,狀態(tài)欄將不再會是浮在我們的window
上悦冀。沒關(guān)系趋翻,我們可以通過下面的方法達到一樣的效果:
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
其實設(shè)置android:windowTranslucentStatus
屬性時,正是系統(tǒng)幫我們設(shè)置了上面的Flag
盒蟆;上面我們在DecorView
上調(diào)用這個方法踏烙,但其實可以在任何一個可見的View
上進行調(diào)用,效果是一樣的历等。下面再補充說明一下setSystemUiVisibility
其他可用的標志:
View.SYSTEM_UI_FLAG_VISIBLE Level 14 默認標記
View.SYSTEM_UI_FLAG_LOW_PROFILE Level 14
低功耗模式, 會隱藏狀態(tài)欄圖標, 在4.0上可以實現(xiàn)全屏讨惩。status bar和navigation bar的相關(guān)圖標會被弱化,比如navigation bar的幾個虛擬鍵會弱化成很細微的小點寒屯。一旦你再次點擊 status bar和navigation bar 的所在區(qū)域荐捻,他們就會再次完全顯現(xiàn)。這種方式的好處是status bar和navigation bar并沒有消失寡夹,仍然在界面上处面,但是它們的細節(jié)變暗了、模糊了菩掏。
View.SYSTEM_UI_FLAG_LAYOUT_STABLE Level 16
保持整個View穩(wěn)定, 常跟bar 懸浮, 隱藏共用, 使View不會因為SystemUI的變化而做layout
View.SYSTEM_UI_FLAG_FULLSCREEN Level 16
狀態(tài)欄隱藏(導(dǎo)航欄仍然顯示)魂角。跟WindowManager.LayoutParams.FLAG_FULLSCREEN有相同的效果(其實不同,因為該標志下statusbar的高度還是會存在智绸,不算真正意義上的全屏)野揪,同時在使用ActionBar的FEATURE_ACTION_BAR_OVERLAY時访忿,啟用SYSTEM_UI_FLAG_FULLSCREEN 會將ActionBar隱藏;該標志一般適用于短期的全屏狀態(tài)而不是長期斯稳。
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN Level 16
狀態(tài)欄上浮于Activity
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION Level 14
暫時隱藏導(dǎo)航欄, 由于導(dǎo)航欄的重要性海铆,當產(chǎn)生細微的用戶交互后,比如單擊屏幕挣惰,都可能會導(dǎo)致navigation bar重新出現(xiàn),源于系統(tǒng)clear掉該標志與SYSTEM_UI_FLAG_FULLSCREEN 標志游添,同SYSTEM_UI_FLAG_IMMERSIVE 標志一起使用可避免被clear
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION Level 16
導(dǎo)航欄上浮于Activity
View.SYSTEM_UI_FLAG_IMMERSIVE Level 19
Kitkat新加入的Flag, 沉浸模式, 跟SYSTEM_UI_FLAG_HIDE_NAVIGATION一起使用才有意義,可以避免系統(tǒng)在產(chǎn)生細微用戶交互時系統(tǒng)clear掉SYSTEM_UI_FLAG_HIDE_NAVIGATION標志通熄。如單獨使用SYSTEM_UI_FLAG_HIDE_NAVIGATION標志時只需單擊屏幕,導(dǎo)航欄就會重新出現(xiàn)找都;如果同時使用該標志唇辨,則不會出現(xiàn),但用戶在導(dǎo)航欄區(qū)域仍然可以主動呼出能耻。呼出后赏枚,對應(yīng)的標志會被清除。
View.SYSTEM_UI_FLAG_IMMERSIVE_STIKY Level 19
需要跟SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 或者 SYSTEM_UI_FLAG_FULLSCREEN 一起使用晓猛。當單獨使用上面的標志時饿幅,任何用戶交互會導(dǎo)致導(dǎo)航欄重新出現(xiàn),從頂部向下滑動會重新呼出狀態(tài)欄戒职,這些操作會導(dǎo)致這些標志被clear掉栗恩。如果同時指定SYSTEM_UI_FLAG_IMMERSIVE_STIKY 標志,那么對應(yīng)標志將不會被清除洪燥,且呼出隱藏的bar后會自動再隱藏掉
總結(jié)
只有Aos 4.4 API 19 KitKat
以上版本才支持沉浸式狀態(tài)欄磕秤!