首先: android 的透明狀態(tài)欄和沉浸式是兩個(gè)不同的東西但校,但是又相互交錯(cuò)告材,不要混淆。透明狀態(tài)欄是指將狀態(tài)欄設(shè)置為透明或者半透明驳规,沉浸式是指,將頁面的布局“沉浸”在狀態(tài)欄下面创肥,如果這時(shí)候?qū)顟B(tài)欄設(shè)置為透明达舒,那么狀態(tài)欄和手機(jī)頁面看以來是一個(gè)整體值朋,增大了屏幕的利用空間。如果設(shè)置了沉浸式狀態(tài)欄不透明巩搏,毫無疑問布局將會(huì)被狀態(tài)欄遮擋昨登。
在之前先講講Android的主題設(shè)置,和將狀態(tài)欄設(shè)置透明帶來的變化贯底。
對于現(xiàn)在開發(fā)項(xiàng)目我們一般使用的是 Theme.AppCompat.xxx兼容包里面的主題
<style name="AppTheme1" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorPrimary</item>
</style>
為了兼容不同版本丰辣,會(huì)建立多個(gè)版本兼容的文件夾
比如:
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorPrimary</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
前三個(gè)屬性分別表示表示的顏色用一張經(jīng)典的圖來對應(yīng)表示:
分別代表toolbar的顏色、狀態(tài)欄的顏色禽捆、輸入法和radiobuttion等的顏色笙什,但是需要注意的是:
在5.0以下的版本,狀態(tài)欄的顏色通過主題設(shè)置是沒有用的胚想,用以上的主題屬性來設(shè)置狀態(tài)欄顏色琐凭,在5.x以下是黑色,自己可以試試浊服。
后三個(gè)屬性是來設(shè)置透明狀態(tài)欄的统屈,android:windowTranslucentStatus、android:windowTranslucentNavigation是4.4以后才有的屬性牙躺,android:statusBarColor是5.0以后才有的屬性愁憔,所以才要分為幾個(gè)value文件夾來存放不同的主題,好在as現(xiàn)在非常智能孽拷,如果你在兼容低版本的情況下吨掌,用了高版本的api會(huì)發(fā)出警告。
設(shè)置狀態(tài)欄透明
那么設(shè)置狀態(tài)欄透明又會(huì)是什么樣子呢脓恕?(分析4.4以上的版本)
有兩種方式設(shè)置狀態(tài)欄透明膜宋,第一種是上面的通過改變主題的方式,這里貼出value-v19进肯、v21的主題參數(shù)
v19
<style name="AppTheme1" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorPrimary</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
========
v21
<style name="AppTheme1" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorPrimary</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
主要區(qū)別只一個(gè)用了actionbar主題激蹲,一個(gè)沒用棉磨,這里是為了嘗試看到更多變化的效果江掩,對這里透明狀態(tài)欄沒影響。
正對以上運(yùn)行效果乘瓤。說明下:
- 4.4版本和5.x版本設(shè)置狀態(tài)欄是有差異的环形,4.4的狀態(tài)欄和底部導(dǎo)航欄都變半透明,但是顏色是漸變的衙傀,而5.x以上是變灰色
- windowTranslucentStatus屬性改變狀態(tài)欄成半透明抬吟,并且布局網(wǎng)上頂,充滿全屏
- windowTranslucentNavigation屬性改變底部導(dǎo)航欄顏色為半透明
- statusBarColor 5.x才有設(shè)置狀態(tài)欄顏色统抬,4.x不是不能設(shè)置顏色的火本。
這里對上面擴(kuò)展下:
為什么setContentView的布局會(huì)頂上去呢危队?再來一張窗口的層級的經(jīng)典圖片
statubar狀態(tài)欄是系統(tǒng)窗口,DecorView是視圖的頂級窗口钙畔,繼承自FramLayout茫陆,他的子View一個(gè)是actionbar,和一個(gè)id為content的FramLyout擎析,這個(gè)content就是setContentView的那個(gè)布局簿盅,通過AS的工具也可以看出來。
至于為什么設(shè)置了透明主題屬性就會(huì)把contentView頂上去呢?這里沒有去探究源碼揍魂,暫且就這么認(rèn)為吧——如果設(shè)置了透明狀態(tài)欄桨醋,decorview和content之間的margin為0,這時(shí)候content布局的大小就是整個(gè)屏幕的大邢终喜最;如果沒有設(shè)置,則margin為狀態(tài)欄的高度加上actionbar的高度(如果有)庄蹋。但是actionbar沒有頂上去返顺,但是有什么方法不讓頂上去呢?有兩種方法蔓肯。
1遂鹊、將跟布局添加:android:fitsSystemWindows="true|false"
<android.support.v7.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:gravity="start"
android:background="#ffffff"
tools:context="com.xc.test.MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitStart"
android:src="@drawable/aaa"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
</android.support.v7.widget.LinearLayoutCompat>
2、代碼設(shè)置
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
注意:android:fitsSystemWindows這個(gè)屬性只有在主題中設(shè)置了[windowTranslucentStatus|windowTranslucentNavigation]屬性或者代碼中調(diào)用window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);才會(huì)生效蔗包。(我目前的驗(yàn)證是這樣)
利用代碼設(shè)置狀態(tài)欄透明
// 設(shè)置狀態(tài)欄全透明
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//設(shè)置根布局頂上去
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
在這里看到6.x的模擬器狀態(tài)欄為什么不是灰色呢秉扑?最后找到了答案,原來通過代碼設(shè)置的透明和通過主題設(shè)置是有區(qū)別的
狀態(tài)欄著色
- 5.x以上的版本
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.setStatusBarColor(setStatusBarColor());
window.setStatusBarColor(setStatusBarColor());這個(gè)方法設(shè)置狀態(tài)欄的顏色5.x以后才有的api调限,4.4版本需要做特殊處理舟陆。
大家發(fā)現(xiàn)沒有,我一直在6.x的模擬器上設(shè)置了一個(gè)actionBar耻矮,然而這個(gè)actionbar沒有沉浸到狀態(tài)欄下面秦躯,正是如此,我們只能舍棄actionbar使用toolbar了裆装,在頁面的布局中加入toolbar
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimaryDark"
app:title="toobar"
>
</android.support.v7.widget.Toolbar>
toolbar隨著布局頂?shù)綘顟B(tài)欄下面踱承,其實(shí)toolbar有兩種用法:
一種是設(shè)置沒有actionbar的主題(你也可以設(shè)置,但是這樣會(huì)重疊)哨免,將toolbar像上面一樣嵌入布局中茎活,toolbar就是一個(gè)普通的布局,實(shí)質(zhì)上toolbar是繼承的ViewGroup琢唾,這樣沒毛病载荔。
另一種是setSupportActionBar(toolbar),讓toolbar替代actionbar采桃,如果是這樣的話懒熙,主題必須是noActionBar的丘损,不然拋異常,這樣子toolbar就會(huì)繼承actionbar的一些特性工扎,比如設(shè)置透明狀態(tài)欄之后不會(huì)將布局頂上去号俐,而且還為你把toolbar填充了高度。當(dāng)然前提是不能調(diào)用window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);如果調(diào)用了這個(gè)方法定庵,照樣會(huì)頂上去的吏饿,也可以用fitsSystemWindows來配合使用,多嘗試蔬浙。
就這樣猪落,當(dāng)狀態(tài)欄為透明,toolbar又頂上去了畴博,這樣就顯得整個(gè)主題風(fēng)格一致笨忌,這就是沉浸式。
還有就是app最上端為圖片的時(shí)候希望這樣設(shè)計(jì):
這叫透明狀態(tài)欄俱病,反正也沒個(gè)規(guī)范的說法官疲,我就這么叫的。
4.4狀態(tài)欄著色
4.4版本唯一一個(gè)和5.x版本不一樣的地方就是4.4沒有改變狀態(tài)欄顏色的api亮隙,只有改變透明度的api途凫,那怎么解決這個(gè)問題呢?
我們都知道溢吻,整個(gè)app展現(xiàn)在我們眼前的最外層的視圖為DecorView维费,實(shí)質(zhì)上是一個(gè)FramLayout,狀態(tài)欄是系統(tǒng)的窗口促王,覆蓋在DecorView之上的犀盟,DecorView里面有我們的content,既然是這樣蝇狼,我們可以在DecorView里面加一個(gè)布局阅畴,覆蓋在content之上,通過設(shè)置狀態(tài)欄透明迅耘,改變這個(gè)View的顏色贱枣,這樣就造成了改變狀態(tài)欄顏色的假象。這些事情早就有人遭了輪子豹障,在這里就不重復(fù)了冯事。
StatusBarUtil
總結(jié):
- 4.4以上才有沉浸式狀態(tài)欄
- 設(shè)置狀態(tài)欄透明或者任意顏色(可以通過主題和代碼方法)使得布局頂?shù)綘顟B(tài)欄下面
- toolbar替換actionbar使得沉浸式得以實(shí)現(xiàn)
下一篇寫toolbar的使用和沉浸式BaseActivity基類的封裝