前言
網(wǎng)上已經(jīng)有很多有關(guān)于系統(tǒng)狀態(tài)欄的解決方案,這篇文章也不會(huì)有什么新奇的解決方案,都是本人經(jīng)過(guò)自己試驗(yàn),統(tǒng)計(jì)提煉出來(lái)的相對(duì)靠譜的一套解決方案.
如果是android大懦仁可以忽略本文,怕讓您賤笑.只面向小白,幫助小白減少摸索的時(shí)間.
關(guān)于術(shù)語(yǔ)
網(wǎng)上有很多爭(zhēng)論:
你這狀態(tài)欄是變色龍狀態(tài)欄,不是沉浸式的
這應(yīng)該是沉浸式的狀態(tài)欄吧,系統(tǒng)欄與actionbar顏色設(shè)為一致
我只想說(shuō)去你妹的,老子只要自己的app的狀態(tài)欄能和主題顏色一致就行了,定義那么多術(shù)語(yǔ),讓我等小白情以何堪?
吐槽歸吐槽,但還是不得不去試著理解下這些術(shù)語(yǔ)怎么來(lái)的,引用這里的一段話:
- 沉浸式全屏模式
隱藏status bar(狀態(tài)欄)使屏幕全屏,讓Activity接收所有的(整個(gè)屏幕的)觸摸事件急黎。 - 透明化系統(tǒng)狀態(tài)欄
透明化系統(tǒng)狀態(tài)欄,使得布局侵入系統(tǒng)欄的后面棚放,必須啟用fitsSystemWindows屬性來(lái)調(diào)整布局才不至于被系統(tǒng)欄覆蓋紊扬。
因此,我就這樣理解了:
沉浸式不就是隱藏狀態(tài)欄嘛,狀態(tài)欄不見(jiàn)了?這不就是app全屏模式嘛?wtf?
而透明式式狀態(tài)欄就是讓app的內(nèi)容布局可以擴(kuò)展到系統(tǒng)狀態(tài)欄?這里有個(gè)問(wèn)題就是為什么能在系統(tǒng)狀態(tài)欄還顯示的情況下,將內(nèi)容布局?jǐn)U展到系統(tǒng)狀態(tài)欄?恩,這應(yīng)該很好理解,就是Z坐標(biāo)系的作用了,系統(tǒng)狀態(tài)欄是覆蓋在內(nèi)容布局上面的,并且是透明的。
貌似這里所謂透明化系統(tǒng)狀態(tài)欄才是本菜想要的,不管了,現(xiàn)在開(kāi)始一一試驗(yàn),至于這概念理解的對(duì)不對(duì),管他呢荣茫?那到底應(yīng)該叫什么,那我就叫自適應(yīng)狀態(tài)欄,行不行?
前提條件
讓系統(tǒng)狀態(tài)欄顏色隨app主題顏色變化而變化這一設(shè)計(jì),毫無(wú)疑問(wèn),也是向ios學(xué)習(xí)的:從android4.4開(kāi)始引進(jìn)的,并且在5.0進(jìn)行了改進(jìn)场靴。因此,也只能將這一特性應(yīng)用在android4.4以上的手機(jī),無(wú)法做到全部適配啡莉。記得stormzhang(貌似是)曾說(shuō)過(guò):
作為一個(gè)android程序員,還能有什么比做出ios風(fēng)格的app更感到悲哀的呢?哎...
兩種情況下的解決方案:
- 使用toolbar
這種方案相對(duì)簡(jiǎn)單,個(gè)人喜歡這種方案,本菜雖菜,但喜歡緊跟潮流。toolbar太好用了, - 不使用toolbar
1. 使用toolbar的解決方案
這個(gè)方法參照了這里,薄荷app的toolbar適配方案
其基本原理就是:
theme里添加style: <item name="android:windowTranslucentStatus"> true </item>后,包含toolbar的內(nèi)容布局就可以擴(kuò)展至系統(tǒng)狀態(tài)欄,狀態(tài)欄會(huì)覆蓋在toolbar上,如果此時(shí)使用android:fitsSystemWindows="true",就可以調(diào)整內(nèi)容布局(估計(jì)也是在根布局上加padding)恢復(fù)到原來(lái)位置.但是,上面的解決方案確是給toolbar加上一個(gè)padding-top="25dp",這樣就可以做到系統(tǒng)狀態(tài)欄的顏色和toolbar的顏色保持一致.具體方案可以參照上面的薄荷app的方案鏈接.
簡(jiǎn)述下步驟(只是簡(jiǎn)述,有疑問(wèn)請(qǐng)參照上面薄荷app的鏈接即可):
- 引入v7包,并在布局里添加toolbar
compile ‘com.android.support:appcompat-v7:22.2.1’
- 在代碼中設(shè)置透明化:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
local LayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}
當(dāng)然也可以在theme的樣式文件里添加style:<item name="android:windowTranslucentStatus">true</item>,效果相同,但是大神們都說(shuō)樣式文件里設(shè)置在某些型號(hào)里不生效.ok,大家都在代碼里設(shè)置就好了
- 給toolbar加上padding-top,toolbar代碼如下
<android.support.v7.widget.Toolbar android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/toolbar_padding_top"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="#30469b">
<TextView android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="@string/app_name"/>
</android.support.v7.widget.Toolbar>
4.其中android:paddingTop="@dimen/toolbar_padding_top"要在values中的styles文件里設(shè)為0dp,在values-v19的styles里設(shè)為25dp,原因不多說(shuō)了
這樣就可以達(dá)成了我們的目標(biāo),如果只是這樣也就罷了,按照上面做就可以了,關(guān)鍵是本菜是喜歡緊跟潮流的,使用MD風(fēng)格的DrawerLayout+NavigationView時(shí),在android4.4的手機(jī)下,就會(huì)變這樣了:
很明顯,drawerlayout并沒(méi)用被擴(kuò)展至系統(tǒng)狀態(tài)欄,但在android5.0以上效果還是可以的,這讓我很奇怪,只能歸咎于5.0的優(yōu)化了
經(jīng)過(guò)各種折騰終于想起來(lái),可以把fitsSystemWindows的特性用在drawerlayout上試試,最后發(fā)現(xiàn)居然可以,最終將設(shè)置windowTranslucentStatus的代碼調(diào)整如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
local LayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
//將側(cè)邊欄頂部延伸至status bar
mDrawerLayout.setFitsSystemWindows(true);
//將主頁(yè)面頂部延伸至status bar;雖默認(rèn)為false,但經(jīng)測(cè)試,DrawerLayout需顯示設(shè)置
mDrawerLayout.setClipToPadding(false);
}
}
最終android4.4上也可以顯示正常:
2. 不使用toolbar的解決方案
不使用toolbar時(shí),而是actionbar時(shí),因?yàn)閍ctionbar不好定制,所以無(wú)法采用上面那個(gè)方法,只能采用其它方法,這里的方案主要參考這里:Translucent System Bar 的最佳實(shí)踐
這篇簡(jiǎn)書看的本菜暈乎乎的,仔細(xì)看下來(lái),其實(shí)都是基于一個(gè)原理:
不管有沒(méi)有actionbar,內(nèi)容布局的背景顏色一律設(shè)為主題顏色,然后有actionbar的話,就將actionbar與內(nèi)容布局的背景顏色同時(shí)設(shè)為主題顏色,然后,每個(gè)內(nèi)容布局的根布局都要設(shè)上fitsSystemWindows="true"進(jìn)行調(diào)整,感覺(jué)超麻煩有沒(méi)有?
不說(shuō)多少,簡(jiǎn)述步驟:
- 在代碼中設(shè)置透明化,步驟同上
- 設(shè)置內(nèi)容布局的根布局的背景顏色為主題顏色,同時(shí)設(shè)置fitsSystemWindows="true"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:fitsSystemWindows="true"
android:orientation="vertical">
- 在內(nèi)容布局的下面再設(shè)置一層內(nèi)容布局,設(shè)背景顏色為白色(或其它顏色):
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/c_light_white"
android:gravity="center"
android:orientation="vertical">
至此,這種方案也完成了,看下效果:
可以看出,這種方案一般情況下,還是可行的,但是有三個(gè)問(wèn)題:
- 如果用上drawerlayout+navigationview,actionbar就會(huì)覆蓋在側(cè)邊欄上(如上圖),暫時(shí)未找到解決方案,但是我想說(shuō)你都用drawerlayout+navigationview了,為何不用toolbar,因此這個(gè)問(wèn)題應(yīng)該不是問(wèn)題,況且還可以使用其它的側(cè)邊欄實(shí)現(xiàn)方式,各位道友可以試試
- 這種方案在每個(gè)根布局上都要設(shè)fitsSystemWindows="true"進(jìn)行調(diào)整,當(dāng)然上面也有優(yōu)化方案,可仍然覺(jué)得很麻煩,
- 每個(gè)根布局里都要多加的一層布局來(lái)覆蓋根布局的背景主題顏色
因此,這種方案的確不是上上之選.
總結(jié)
本文主要在考慮使用標(biāo)題欄(actionbar/toolbar)的情況下,做出的方案,當(dāng)然你也可以自定義標(biāo)題欄,或者不使用標(biāo)題欄;其實(shí)都可以基于上面一樣的道理:
在狀態(tài)欄透明化的前提下,調(diào)整頂部view的padding-top,來(lái)達(dá)到狀態(tài)欄自適應(yīng)一體化的目的
網(wǎng)上還有其它蠻多的解決方案,如:
- 使用開(kāi)源庫(kù)SystemBarTint,這個(gè)庫(kù)也挺不錯(cuò)的,可以動(dòng)態(tài)改變系統(tǒng)狀態(tài)欄顏色,但是作者已經(jīng)2年沒(méi)有維護(hù)了,現(xiàn)在技術(shù)更新迭代這么快,鬼知道這個(gè)庫(kù)會(huì)不會(huì)出現(xiàn)什么問(wèn)題,因此可以放棄使用了
- 如果不怕麻煩,還可以new一個(gè)高度和狀態(tài)欄一樣高的view,插入到內(nèi)容布局的上面,但是,想想都覺(jué)得麻煩,我也懶得試了
關(guān)于本文中的樣例代碼已上傳至github,歡迎star,有問(wèn)題也歡迎各位擼友,道友們來(lái)指正.