Android 狀態(tài)欄著色實(shí)踐

** 本篇文章已授權(quán)微信公眾號(hào) guolin_blog (郭霖)獨(dú)家發(fā)布*

狀態(tài)欄著色牢硅,也就是我們經(jīng)常聽(tīng)到的沉浸式狀態(tài)欄蹬耘,關(guān)于沉浸式的稱呼網(wǎng)上也有很多吐槽的,這里就不做過(guò)多討論了减余,以下我們統(tǒng)稱狀態(tài)欄著色综苔,這樣我覺(jué)得更加容易理解。

從Android4.4開(kāi)始,才可以實(shí)現(xiàn)狀態(tài)欄著色如筛,并且從5.0開(kāi)始系統(tǒng)更加完善了這一功能堡牡,可直接在主題中設(shè)置<item name="colorPrimaryDark">@color/colorPrimaryDark</item>或者getWindow().setStatusBarColor(color)來(lái)實(shí)現(xiàn),但畢竟4.4+的機(jī)器還有很大的占比杨刨,所以就有必要尋求其它的解決方案悴侵。

第一種方案:

1、首先將手機(jī)手機(jī)狀態(tài)欄透明化:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0及以上
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4到5.0
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        }

在相應(yīng)的Activity或基類(lèi)執(zhí)行這段代碼就ok了拭嫁。
可見(jiàn)在4.4到5.0的系統(tǒng)可免、5.0及以上系統(tǒng)的處理方式有所不同,除了這種代碼修改額方式外做粤,還可以通過(guò)主題來(lái)修改浇借,需要在values、values-v19怕品、values-v21目錄下分別創(chuàng)建相應(yīng)的主題:

//values
<style name="TranslucentTheme" parent="AppTheme">
</style>

//values-v19
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">false</item>
</style>

//values-v21
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
</style>

給相應(yīng)Activity或Application設(shè)置該主題就ok了妇垢。
兩種方式根據(jù)需求選擇就好了,到這里我們就完成了第一步肉康,將狀態(tài)欄透明化了闯估。

2、給狀態(tài)欄著色
完成了第一步吼和,我們開(kāi)始給狀態(tài)欄加上想要的色彩吧涨薪!
將狀態(tài)欄透明化后,直接運(yùn)行項(xiàng)目會(huì)發(fā)現(xiàn)界面布局直接延伸到狀態(tài)欄炫乓,針對(duì)這種情況首先可以在布局文件使用android:fitsSystemWindows="true"屬性讓布局不延伸到狀態(tài)欄刚夺,接下來(lái)添加一個(gè)和狀態(tài)欄高、寬相同的指定顏色View來(lái)覆蓋被透明化的狀態(tài)欄末捣,或者使布局的背景顏色為需要的狀態(tài)欄顏色侠姑。這兩種方式在后邊會(huì)說(shuō)到,這里我們先看另外一種方式箩做,也是個(gè)人比較喜歡的莽红。我們分一下幾種場(chǎng)景來(lái)討論:

先做一些準(zhǔn)備工作,在values邦邦、values-v19目錄添加如下尺寸:

//values
<dimen name="padding_top">0dp</dimen>

//values-v19
<dimen name="padding_top">25dp</dimen>

關(guān)于25dp安吁,在有些系統(tǒng)上可能有誤差,這里不做討論圃酵!

2.1 頁(yè)面頂部使用Toolbar(或自定義title)
一般情況狀態(tài)欄的顏色和Toolbar的顏色相同柳畔,既然狀態(tài)欄透明化后馍管,布局頁(yè)面延伸到了狀態(tài)欄郭赐,何不給Toolbar加上一個(gè)狀態(tài)欄高度的頂部padding呢:

<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:paddingTop="@dimen/padding_top"
        android:theme="@style/AppTheme.AppBarOverlay" />

效果如下:


1

至于自定義title的情況經(jīng)測(cè)試也ok的,圖就不貼了,有興趣可看代碼捌锭。

2.2俘陷、 DrawerLayout + NavigationView + Toolbar
同樣先給Toolbar設(shè)置頂部padding,在4.4系統(tǒng)上看下效果:

2

NavigationView竟然沒(méi)延伸到狀態(tài)欄观谦,好吧拉盾,繼續(xù)修改,當(dāng)系統(tǒng)版本小于5.0時(shí)豁状,進(jìn)行如下設(shè)置:

private void navViewToTop() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            mDrawerLayout.setFitsSystemWindows(true);
            mDrawerLayout.setClipToPadding(false);
        }
    }

再看效果:


3

2.3捉偏、頁(yè)面頂部是一張圖片
這種其實(shí)是最簡(jiǎn)單的,因?yàn)闋顟B(tài)欄透明化后泻红,布局已經(jīng)延伸到狀態(tài)夭禽,所以不需要其它額外操作:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@mipmap/top_image" />
</LinearLayout>

效果如下:


4

2.4、頁(yè)面底部切換Tab + fragment
某些情況下谊路,當(dāng)我們的頁(yè)面采用底部切換Tab + 多個(gè)fragment時(shí)讹躯,可能每個(gè)fragment的頂部顏色不一樣。如何實(shí)現(xiàn)狀態(tài)欄顏色跟隨fragment切換來(lái)變化呢缠劝?其實(shí)原理和2.1類(lèi)似潮梯,這里我們每個(gè)fragment采用自定義的Title,先看FragmentOne的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ff9900"
        android:paddingTop="@dimen/padding_top">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center"
            android:text="fragment one" />
    </LinearLayout>
</LinearLayout>

我們?cè)O(shè)置Title的背景為橙黃色惨恭、同時(shí)設(shè)置paddingTop秉馏,F(xiàn)ragmentTwo的布局類(lèi)似,只是Title的背景為藍(lán)色脱羡。然后將兩個(gè)Fragment添加到Activity中沃饶,最后看下切換的效果:

5

嗯,效果還是不錯(cuò)的轻黑,沒(méi)有延遲的情況糊肤!可惜沒(méi)早點(diǎn)發(fā)掘這種方式,以前的方案效果略不理想氓鄙。

第二種方案:

在方案一中馆揉,我們沒(méi)有使用android:fitsSystemWindows="true"屬性,而是將布局延伸到狀態(tài)欄來(lái)處理抖拦,這次我們使用android:fitsSystemWindows="true"屬性升酣,不讓布局延伸到狀態(tài)欄,這時(shí)狀態(tài)欄就是透明的态罪,然后添加一個(gè)和狀態(tài)欄高噩茄、寬相同的指定顏色View來(lái)覆蓋被透明化的狀態(tài)欄。我們一步步來(lái)實(shí)現(xiàn)复颈。

1绩聘、第一步還是先將狀態(tài)欄透明化,方法同上。
2凿菩、在布局文件中添加android:fitsSystemWindows="true"屬性:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:title="第二種方案" />
</LinearLayout>

3机杜、創(chuàng)建View并添加到狀態(tài)欄:

private void addStatusBarView() {
        View view = new View(this);
        view.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                getStatusBarHeight(this));
        ViewGroup decorView = (ViewGroup) findViewById(android.R.id.content);
        decorView.addView(view, params);
    }

原理很簡(jiǎn)單,但是要額外寫(xiě)這些代碼衅谷。椒拗。。最后看下效果:


6

第三種方案:

和方案二類(lèi)似获黔,同樣使用android:fitsSystemWindows="true"屬性蚀苛,再修改布局文件的根布局為需要的狀態(tài)欄顏色,因根布局的顏色被修改玷氏,所以你需要在里邊多嵌套一層布局枉阵,來(lái)指定界面的主背景色,比如白色等等预茄,否則就和狀態(tài)欄顏色一樣了兴溜。說(shuō)起來(lái)有點(diǎn)抽象,還是看具體的例子吧:
1耻陕、先將狀態(tài)欄透明化拙徽,方法同上。
2诗宣、修改布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff9900"
    android:fitsSystemWindows="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ff9900"
            android:theme="@style/AppTheme.AppBarOverlay"
            app:title="第三種方案" />
    </LinearLayout>
</RelativeLayout>

修改完了膘怕,看效果:


7

如果項(xiàng)目有幾十個(gè)界面,這樣的方式修改起來(lái)還是挺累的召庞,你還要考慮各種嵌套問(wèn)題岛心。

后兩種方案的例子相對(duì)簡(jiǎn)單,有興趣的話你可以嘗試更多的場(chǎng)景篮灼!

三種方式如何選擇忘古,相信到這里你應(yīng)該有答案了吧,我個(gè)人更喜歡第一種诅诱!
如果你有更好的方案髓堪,歡迎指點(diǎn)哦!

這里是測(cè)試代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末娘荡,一起剝皮案震驚了整個(gè)濱河市干旁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炮沐,老刑警劉巖争群,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異大年,居然都是意外死亡换薄,警方通過(guò)查閱死者的電腦和手機(jī)玉雾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)专控,“玉大人,你說(shuō)我怎么就攤上這事遏餐÷赘” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵失都,是天一觀的道長(zhǎng)柏蘑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)粹庞,這世上最難降的妖魔是什么咳焚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮庞溜,結(jié)果婚禮上革半,老公的妹妹穿的比我還像新娘。我一直安慰自己流码,他們只是感情好又官,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著漫试,像睡著了一般六敬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驾荣,一...
    開(kāi)封第一講書(shū)人閱讀 49,829評(píng)論 1 290
  • 那天外构,我揣著相機(jī)與錄音,去河邊找鬼播掷。 笑死审编,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的歧匈。 我是一名探鬼主播割笙,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼眯亦!你這毒婦竟也來(lái)了伤溉?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤妻率,失蹤者是張志新(化名)和其女友劉穎乱顾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宫静,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡走净,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年券时,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伏伯。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡橘洞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出说搅,到底是詐尸還是另有隱情炸枣,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布弄唧,位于F島的核電站适肠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏候引。R本人自食惡果不足惜侯养,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澄干。 院中可真熱鬧逛揩,春花似錦、人聲如沸麸俘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)疾掰。三九已至搂誉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間静檬,已是汗流浹背炭懊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拂檩,地道東北人侮腹。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像稻励,于是被迫代替她去往敵國(guó)和親父阻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

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