Android透明狀態(tài)欄與沉浸模式全解

Android透明狀態(tài)欄與沉浸模式全解

現(xiàn)在如今利用狀態(tài)欄做文章的主要就是如下四種場景了,先上圖

  • 網(wǎng)易云音樂 狀態(tài)欄與標(biāo)題欄同色呻征,無縫銜接
  • 多看閱讀 全屏沉浸閱讀(視頻谆级,游戲同理)
  • 淘寶 狀態(tài)欄深色
  • 餓了么 圖片延伸至狀態(tài)欄下面

透明狀態(tài)欄模式就是大家說的"沉浸式狀態(tài)欄"了.

沉浸模式是一般用于小說洞拨、視頻扯罐、游戲。將用戶的注意完全聚焦在內(nèi)容上烦衣,是真正的沉浸模式.

從3.x版本開始, 系統(tǒng)DecorView提供了setSystemUiVisibility方法, 可以通過設(shè)置Flag更改所謂SystemUI的屬性歹河,可以操作各種狀態(tài)欄掩浙,導(dǎo)航欄的的顯示與隱藏效果。非常好用秸歧,有篇很好的總結(jié)文章Android Activity 全屏方法總結(jié)
調(diào)用方式:

getWindow().getDecorView().setSystemUiVisibility(
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
);

不同的標(biāo)記用|連接厨姚,這里著重解釋一下這幾個(gè)標(biāo)記

  • View.SYSTEM_UI_FLAG_LAYOUT_STABLE Level 16
    保持整個(gè)View穩(wěn)定,使View不會(huì)因?yàn)镾ystemUI的變化而做layout,常跟statusbar 懸浮, 隱藏共用,若不設(shè)置的話键菱,statusbar的的顯示和隱藏則會(huì)導(dǎo)致ContentView重新計(jì)算大小并繪制谬墙,因此這個(gè)標(biāo)記通常是必須的

  • View.SYSTEM_UI_FLAG_FULLSCREEN Level 16
    狀態(tài)欄隱藏,完全不見了经备,就如同在看視頻時(shí)拭抬,屏幕上沒有任何內(nèi)容之外的東西

  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN Level 16
    狀態(tài)欄透明,懸浮在浮于Activity的上面侵蒙,想像有個(gè)z軸造虎,這時(shí)activity可以完全占用整個(gè)屏幕,而之前我們的屏幕還要分一些給statusbar

  • View.SYSTEM_UI_FLAG_HIDE_NAVIGATION Level 14
    隱藏導(dǎo)航欄, 性質(zhì)如SYSTEM_UI_FLAG_FULLSCREEN

  • View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION Level 16
    導(dǎo)航欄上浮于Activity纷闺,性質(zhì)如SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

1.首先看效果圖(1)和(3)算凿,這兩個(gè)的實(shí)現(xiàn)原理其實(shí)一樣,就是狀態(tài)欄著色的顏色不同犁功,又兩種實(shí)現(xiàn)思路

1.直接將狀態(tài)欄的顏色設(shè)置為目標(biāo)顏色
window.setStatusBarColor(int);

它只適用于5.0之后氓轰。因此直接設(shè)置statusBar顏色的方式在5.0以下不行

2.將狀態(tài)欄設(shè)置為"透明+懸浮",這時(shí)我們的布局就可以延伸到狀態(tài)欄下面了波桩,然后在activity的布局里面制造一塊和狀態(tài)欄等尺寸的view,設(shè)置需要的背景顏色即可请敦,因?yàn)闋顟B(tài)欄是透明的镐躲,因此看起來就像是狀態(tài)欄被上了色一樣,效果相同侍筛。通過添加這個(gè)標(biāo)記便可以實(shí)現(xiàn)我們需要的"透明+懸浮"效果萤皂,
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

順變說下清除標(biāo)記的方法
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

其實(shí)我們查看FLAG_TRANSLUCENT_STATUS的源碼就會(huì)發(fā)現(xiàn),它其實(shí)就是上面說的system UI visibility flags里面的穩(wěn)定布局SYSTEM_UI_FLAG_LAYOUT_STABLE和懸浮status標(biāo)記的組合

* <p>When this flag is enabled for a window, it automatically sets
* the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and{@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.</p>
*/
public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;

這就很容易理解了匣椰,現(xiàn)在直接上全部代碼

 /**
 * 思路:直接設(shè)置狀態(tài)欄的顏色
 */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setStatusBarUpperAPI21() {
    Window window = getWindow();
    //取消設(shè)置懸浮透明狀態(tài)欄,ContentView便不會(huì)進(jìn)入狀態(tài)欄的下方了
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    //設(shè)置狀態(tài)欄顏色
    window.setStatusBarColor(getResources().getColor(R.color.bg_green));
}

/**
 * 思路:設(shè)置狀態(tài)欄懸浮透明裆熙,然后制造一個(gè)和狀態(tài)欄等尺寸的View設(shè)置好顏色填進(jìn)去,就好像是狀態(tài)欄著色了一樣
 */
private void setStatusBarUpperAPI19() {
    Window window = getWindow();
    //設(shè)置懸浮透明狀態(tài)欄
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    ViewGroup mContentView = (ViewGroup) findViewById(Window.ID_ANDROID_CONTENT);
    int statusBarHeight = getStatusBarHeight();
    int statusColor = getResources().getColor(R.color.bg_green);

    View mTopView = mContentView.getChildAt(0);
    if (mTopView != null && mTopView.getLayoutParams() != null &&
            mTopView.getLayoutParams().height == statusBarHeight) {
        mTopView.setBackgroundColor(statusColor);
        return;
    }

    //制造一個(gè)和狀態(tài)欄等尺寸的 View
    mTopView = new View(this);
    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight);
    mTopView.setBackgroundColor(statusColor);
    //將view添加到第一個(gè)位置
    mContentView.addView(mTopView, 0, lp);
}

private int getStatusBarHeight() {
    int result = 0;
    int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resId > 0) {
        result = getResources().getDimensionPixelSize(resId);
    }
    return result;
}

這里注意為什么還要區(qū)分5.0和4.4不同的方案來實(shí)現(xiàn)禽笑,因?yàn)閃indowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS這個(gè)標(biāo)記在6.0上不是全透明而是半透明的入录,那么如果要實(shí)現(xiàn)效果(1)網(wǎng)易云音樂那樣的效果的話就不行了,所以在5.0以上的版本我們直接設(shè)置statusBar的顏色佳镜。5.0以下通過制造一個(gè)和statusbar等尺寸的view著色填進(jìn)去僚稿。

最終的效果如下,讓4.4也有了差不多的效果:


而效果(3)就是改了個(gè)深色的顏色就行了:


2.看效果圖(4)蟀伸,這就是讓圖片延伸到狀態(tài)欄下蚀同,和1一樣的思路缅刽,用純xml和純代碼均可實(shí)現(xiàn)

  • XML方式實(shí)現(xiàn):
    xml方式就是通過為acitivity設(shè)置style的方式實(shí)現(xiàn),因?yàn)椴煌陌姹拘枰呐渲貌煌缆纾蛭覀優(yōu)?.4和5.0建立values文件夾和styles文件衰猛,并在樣式文件中建立相同名字的樣式,這樣系統(tǒng)就能判斷手機(jī)版本自動(dòng)使用對應(yīng)版本values文件夾下的樣式刹孔,如圖所示啡省,注意路徑

values/styles.xml添加內(nèi)容:
<style name="fullScreenTheme" parent="AppTheme">
</style>

values-v19/styles.xml添加內(nèi)容:

    <style name="fullScreenTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

values-v21/styles.xml添加內(nèi)容:

    <style name="fullScreenTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowTranslucentStatus">false</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

windowTranslucentStatus:設(shè)置透明懸浮狀態(tài)欄,4.4就有
windowTranslucentNavigation:設(shè)置透明懸浮導(dǎo)航欄芦疏,4.4就有

注意既然windowTranslucentStatus在4.4就有了冕杠,為什么在5.0的style要設(shè)置windowTranslucentStatus為false并且呢,其實(shí)這個(gè)問題前面就說過了

window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

<item name="android:windowTranslucentStatus">true</item>
看出來了嗎酸茴,對他們倆其實(shí)是一個(gè)東西分预,一個(gè)是xml實(shí)現(xiàn),一個(gè)是代碼實(shí)現(xiàn)
所以windowTranslucentStatus在6.0上的效果是半透明的薪捍。效果是這樣的笼痹,

而我們的最終效果:


另外,如果加了DrawerLayout酪穿,打開是狀態(tài)欄在5.0以上沒有任何問題凳干,但是在4.4就是是灰色的。需要添加兩行代碼做處理:

    mDrawerLayout.setFitsSystemWindows(true);
    mDrawerLayout.setClipToPadding(false);

setFitsSystemWindows方法的作用是是否為系統(tǒng)默認(rèn)的裝飾預(yù)留空間
setClipToPadding方法是使得繪制區(qū)域可以延伸到padding區(qū)域

其實(shí)這里用了這兩個(gè)方法雖然有效被济,但是我也不知道為什么救赐,有知道朋友請告訴我。

這樣我們就完全使用代碼完美解決了效果(4)只磷。

  • 代碼實(shí)現(xiàn):
    主要就是setSystemUiVisibility的運(yùn)用

    public void onShow() {
    //5.0以上手動(dòng)設(shè)置statusBar為透明经磅。不能使用getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    //因?yàn)檫@在4.4,5.0確實(shí)是全透明,但是在6.0是半透明!!!
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    getWindow().setStatusBarColor(Color.TRANSPARENT);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

          getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
      }
    
      getWindow().getDecorView().setSystemUiVisibility(
              View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                      | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                      | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    
      );
    

    }

3.效果(2)全屏沉浸钮追,如小說预厌,視頻,游戲

在看完setSystemUiVisibility的各種flag的左右后元媚,應(yīng)該可以憑自己的需要組合搭配flag來實(shí)現(xiàn)全屏了轧叽,直接上代碼:

public void onHide() {


    //4.1及以上通用flags組合
    int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        getWindow().getDecorView().setSystemUiVisibility(
                flags | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
        );
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        getWindow().getDecorView().setSystemUiVisibility(flags);
    }
}

就這么幾行代碼,注意這個(gè)全屏是可以支持到4.1的

參考:
Android Activity 全屏方法總結(jié)
Android 系統(tǒng)狀態(tài)欄沉浸式/透明化完整解決方案
Android 狀態(tài)欄全透明策略
Android開發(fā):Translucent System Bar 的最佳實(shí)踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市刊棕,隨后出現(xiàn)的幾起案子炭晒,更是在濱河造成了極大的恐慌,老刑警劉巖甥角,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腰埂,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜈膨,警方通過查閱死者的電腦和手機(jī)屿笼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門牺荠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人驴一,你說我怎么就攤上這事休雌。” “怎么了肝断?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵杈曲,是天一觀的道長。 經(jīng)常有香客問我胸懈,道長担扑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任趣钱,我火速辦了婚禮涌献,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘首有。我一直安慰自己燕垃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布井联。 她就那樣靜靜地躺著卜壕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烙常。 梳的紋絲不亂的頭發(fā)上轴捎,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音蚕脏,去河邊找鬼侦副。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蝗锥,可吹牛的內(nèi)容都是我干的跃洛。 我是一名探鬼主播率触,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼终议,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了葱蝗?” 一聲冷哼從身側(cè)響起穴张,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎两曼,沒想到半個(gè)月后皂甘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悼凑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年偿枕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了璧瞬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡渐夸,死狀恐怖嗤锉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情墓塌,我是刑警寧澤瘟忱,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站苫幢,受9級(jí)特大地震影響访诱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜韩肝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一触菜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伞梯,春花似錦玫氢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喻旷,卻和暖如春生逸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背且预。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工槽袄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锋谐。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓遍尺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涮拗。 傳聞我的和親對象是個(gè)殘疾皇子乾戏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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

  • 關(guān)于沉浸式狀態(tài)欄一詞的說法從何而來我們無從考證。但這確實(shí)是個(gè)錯(cuò)誤的說法先引用官方的一段話三热。 Immersive f...
    ifjgm閱讀 9,075評(píng)論 3 46
  • 前言在使用App的過程中,如果細(xì)心觀察,我們會(huì)發(fā)現(xiàn),某些應(yīng)用頂部菜單欄顏色會(huì)延伸到系統(tǒng)狀態(tài)欄中鼓择,使得菜單欄和狀態(tài)欄...
    heyzhuyue閱讀 769評(píng)論 0 1
  • 前言 原文:http://blog.csdn.net/mybeta/article/details/5076032...
    naturs閱讀 23,107評(píng)論 8 70
  • 前言 這種效果從android4.4開始引進(jìn)的,并且在5.0進(jìn)行了改進(jìn)。因此,也只能將這一特性應(yīng)用在android...
    谷歌哥哥閱讀 1,509評(píng)論 0 2
  • 前言 首先請大家看幾張圖: 以上的效果就漾,一般我們統(tǒng)稱為沉浸式狀態(tài)欄呐能。其實(shí),這種叫法不是很準(zhǔn)確抑堡,而且也沒有沉浸式狀態(tài)...
    宇是我閱讀 3,843評(píng)論 2 28