Android 系統(tǒng)狀態(tài)欄沉浸式/透明化完整解決方案

前言

網(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)的,引用這里的一段話:

  1. 沉浸式全屏模式
    隱藏status bar(狀態(tài)欄)使屏幕全屏,讓Activity接收所有的(整個(gè)屏幕的)觸摸事件急黎。
  2. 透明化系統(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更感到悲哀的呢?哎...

兩種情況下的解決方案:

  1. 使用toolbar
    這種方案相對(duì)簡(jiǎn)單,個(gè)人喜歡這種方案,本菜雖菜,但喜歡緊跟潮流。toolbar太好用了,
  2. 不使用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的鏈接即可):

  1. 引入v7包,并在布局里添加toolbar
compile ‘com.android.support:appcompat-v7:22.2.1’
  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è)置就好了

  1. 給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ì)變這樣了:


android4.4上的效果

很明顯,drawerlayout并沒(méi)用被擴(kuò)展至系統(tǒng)狀態(tài)欄,但在android5.0以上效果還是可以的,這讓我很奇怪,只能歸咎于5.0的優(yōu)化了


android5.0上的效果

經(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上也可以顯示正常:


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)述步驟:

  1. 在代碼中設(shè)置透明化,步驟同上
  2. 設(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">
  1. 在內(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">

至此,這種方案也完成了,看下效果:


android4.4上的效果

可以看出,這種方案一般情況下,還是可行的,但是有三個(gè)問(wèn)題:

  1. 如果用上drawerlayout+navigationview,actionbar就會(huì)覆蓋在側(cè)邊欄上(如上圖),暫時(shí)未找到解決方案,但是我想說(shuō)你都用drawerlayout+navigationview了,為何不用toolbar,因此這個(gè)問(wèn)題應(yīng)該不是問(wèn)題,況且還可以使用其它的側(cè)邊欄實(shí)現(xiàn)方式,各位道友可以試試
  2. 這種方案在每個(gè)根布局上都要設(shè)fitsSystemWindows="true"進(jìn)行調(diào)整,當(dāng)然上面也有優(yōu)化方案,可仍然覺(jué)得很麻煩,
  3. 每個(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)上還有其它蠻多的解決方案,如:

  1. 使用開(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)題,因此可以放棄使用了
  2. 如果不怕麻煩,還可以new一個(gè)高度和狀態(tài)欄一樣高的view,插入到內(nèi)容布局的上面,但是,想想都覺(jué)得麻煩,我也懶得試了

關(guān)于本文中的樣例代碼已上傳至github,歡迎star,有問(wèn)題也歡迎各位擼友,道友們來(lái)指正.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末旨剥,一起剝皮案震驚了整個(gè)濱河市咧欣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轨帜,老刑警劉巖魄咕,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蚌父,居然都是意外死亡哮兰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門苟弛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)喝滞,“玉大人,你說(shuō)我怎么就攤上這事膏秫∮以猓” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)狸演。 經(jīng)常有香客問(wèn)我言蛇,道長(zhǎng),這世上最難降的妖魔是什么宵距? 我笑而不...
    開(kāi)封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮吨拗,結(jié)果婚禮上满哪,老公的妹妹穿的比我還像新娘。我一直安慰自己劝篷,他們只是感情好哨鸭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著娇妓,像睡著了一般像鸡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哈恰,一...
    開(kāi)封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天只估,我揣著相機(jī)與錄音,去河邊找鬼着绷。 笑死蛔钙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的荠医。 我是一名探鬼主播吁脱,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼彬向!你這毒婦竟也來(lái)了兼贡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤娃胆,失蹤者是張志新(化名)和其女友劉穎遍希,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體缕棵,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孵班,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了招驴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片篙程。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖别厘,靈堂內(nèi)的尸體忽然破棺而出虱饿,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布氮发,位于F島的核電站渴肉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏爽冕。R本人自食惡果不足惜仇祭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望颈畸。 院中可真熱鬧乌奇,春花似錦、人聲如沸眯娱。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)徙缴。三九已至试伙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間于样,已是汗流浹背疏叨。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留百宇,地道東北人考廉。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像携御,于是被迫代替她去往敵國(guó)和親昌粤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容