沉浸式狀態(tài)欄ImmersionBar的使用

一斥滤、前言:

自從android4.4開(kāi)始将鸵,android手機(jī)狀態(tài)欄再也不是一成黑的時(shí)代,之前叫做變色龍佑颇,miui6發(fā)布會(huì)把他叫做沉浸式顶掉,之后大家就自然而然的接受了沉浸式這個(gè)名稱,其實(shí)實(shí)際應(yīng)該叫做Translucent Bar挑胸,即為透明狀態(tài)欄痒筒。
??沉浸式實(shí)現(xiàn)原理其實(shí)是使整個(gè)activity布局延伸到整個(gè)屏幕,然后使?fàn)顟B(tài)欄變成透明色茬贵,有些手機(jī)會(huì)有導(dǎo)航欄簿透,同樣也可以把導(dǎo)航欄變成透明色,這樣會(huì)使一些app更加美觀解藻。

狀態(tài)欄

狀態(tài)欄.png

導(dǎo)航欄
導(dǎo)航欄.png

二老充、依賴:

1、android studio

 // 基礎(chǔ)依賴包螟左,必須要依賴
 implementation 'com.gyf.immersionbar:immersionbar:3.0.0'
 // fragment快速實(shí)現(xiàn)(可選)
 implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0'
 // kotlin擴(kuò)展(可選)
 implementation 'com.gyf.immersionbar:immersionbar-ktx:3.0.0'

2啡浊、關(guān)于使用AndroidX支持庫(kù)

請(qǐng)?jiān)谀愕膅radle.properties加入如下配置

   android.useAndroidX=true
   android.enableJetifier=true

3、關(guān)于全面屏

在manifest加入如下配置胶背,四選其一巷嚣,或者都寫(xiě)

① 在manifest的Application節(jié)點(diǎn)下加入

   <meta-data 
     android:name="android.max_aspect"
     android:value="2.4" />

② 在manifest的Application節(jié)點(diǎn)中加入

   android:resizeableActivity="true"

③ 在manifest的Application節(jié)點(diǎn)中加入

   android:maxAspectRatio="2.4"

④ 升級(jí)targetSdkVersion為25以上版本

4、關(guān)于劉海屏

在manifest的Application節(jié)點(diǎn)下加入奄妨,vivo和oppo沒(méi)有找到相關(guān)配置信息

   <!--適配華為(huawei)劉海屏-->
   <meta-data 
     android:name="android.notch_support" 
     android:value="true"/>
   <!--適配小米(xiaomi)劉海屏-->
   <meta-data
     android:name="notch.config"
     android:value="portrait|landscape" />

三涂籽、使用:

1、 基礎(chǔ)用法

    ImmersionBar.with(this).init();

2砸抛、高級(jí)用法评雌,

如果基礎(chǔ)用法不能滿足你的需求树枫,可以試試這里的方法

       ImmersionBar.with(this)
                 .transparentStatusBar()  //透明狀態(tài)欄,不寫(xiě)默認(rèn)透明色
                 .transparentNavigationBar()  //透明導(dǎo)航欄景东,不寫(xiě)默認(rèn)黑色(設(shè)置此方法砂轻,fullScreen()方法自動(dòng)為true)
                 .transparentBar()             //透明狀態(tài)欄和導(dǎo)航欄,不寫(xiě)默認(rèn)狀態(tài)欄為透明色斤吐,導(dǎo)航欄為黑色(設(shè)置此方法搔涝,fullScreen()方法自動(dòng)為true)
                 .statusBarColor(R.color.colorPrimary)     //狀態(tài)欄顏色,不寫(xiě)默認(rèn)透明色
                 .navigationBarColor(R.color.colorPrimary) //導(dǎo)航欄顏色和措,不寫(xiě)默認(rèn)黑色
                 .barColor(R.color.colorPrimary)  //同時(shí)自定義狀態(tài)欄和導(dǎo)航欄顏色庄呈,不寫(xiě)默認(rèn)狀態(tài)欄為透明色,導(dǎo)航欄為黑色
                 .statusBarAlpha(0.3f)  //狀態(tài)欄透明度派阱,不寫(xiě)默認(rèn)0.0f
                 .navigationBarAlpha(0.4f)  //導(dǎo)航欄透明度诬留,不寫(xiě)默認(rèn)0.0F
                 .barAlpha(0.3f)  //狀態(tài)欄和導(dǎo)航欄透明度,不寫(xiě)默認(rèn)0.0f
                 .statusBarDarkFont(true)   //狀態(tài)欄字體是深色贫母,不寫(xiě)默認(rèn)為亮色
                 .navigationBarDarkIcon(true) //導(dǎo)航欄圖標(biāo)是深色文兑,不寫(xiě)默認(rèn)為亮色
                 .autoDarkModeEnable(true) //自動(dòng)狀態(tài)欄字體和導(dǎo)航欄圖標(biāo)變色,必須指定狀態(tài)欄顏色和導(dǎo)航欄顏色才可以自動(dòng)變色哦
                 .autoStatusBarDarkModeEnable(true,0.2f) //自動(dòng)狀態(tài)欄字體變色腺劣,必須指定狀態(tài)欄顏色才可以自動(dòng)變色哦
                 .autoNavigationBarDarkModeEnable(true,0.2f) //自動(dòng)導(dǎo)航欄圖標(biāo)變色绿贞,必須指定導(dǎo)航欄顏色才可以自動(dòng)變色哦
                 .flymeOSStatusBarFontColor(R.color.btn3)  //修改flyme OS狀態(tài)欄字體顏色
                 .fullScreen(true)      //有導(dǎo)航欄的情況下,activity全屏顯示橘原,也就是activity最下面被導(dǎo)航欄覆蓋籍铁,不寫(xiě)默認(rèn)非全屏
                 .hideBar(BarHide.FLAG_HIDE_BAR)  //隱藏狀態(tài)欄或?qū)Ш綑诨騼烧撸粚?xiě)默認(rèn)不隱藏
                 .addViewSupportTransformColor(toolbar)  //設(shè)置支持view變色靠柑,可以添加多個(gè)view寨辩,不指定顏色,默認(rèn)和狀態(tài)欄同色歼冰,還有兩個(gè)重載方法
                 .titleBar(view)    //解決狀態(tài)欄和布局重疊問(wèn)題靡狞,任選其一
                 .titleBarMarginTop(view)     //解決狀態(tài)欄和布局重疊問(wèn)題,任選其一
                 .statusBarView(view)  //解決狀態(tài)欄和布局重疊問(wèn)題隔嫡,任選其一
                 .fitsSystemWindows(true)    //解決狀態(tài)欄和布局重疊問(wèn)題甸怕,任選其一,默認(rèn)為false腮恩,當(dāng)為true時(shí)一定要指定statusBarColor()梢杭,不然狀態(tài)欄為透明色,還有一些重載方法
                 .supportActionBar(true) //支持ActionBar使用
                 .statusBarColorTransform(R.color.orange)  //狀態(tài)欄變色后的顏色
                 .navigationBarColorTransform(R.color.orange) //導(dǎo)航欄變色后的顏色
                 .barColorTransform(R.color.orange)  //狀態(tài)欄和導(dǎo)航欄變色后的顏色
                 .removeSupportView(toolbar)  //移除指定view支持
                 .removeSupportAllView() //移除全部view支持
                 .navigationBarEnable(true)   //是否可以修改導(dǎo)航欄顏色秸滴,默認(rèn)為true
                 .navigationBarWithKitkatEnable(true)  //是否可以修改安卓4.4和emui3.x手機(jī)導(dǎo)航欄顏色武契,默認(rèn)為true
                 .navigationBarWithEMUI3Enable(true) //是否可以修改emui3.x手機(jī)導(dǎo)航欄顏色,默認(rèn)為true
                 .keyboardEnable(true)  //解決軟鍵盤(pán)與底部輸入框沖突問(wèn)題,默認(rèn)為false咒唆,還有一個(gè)重載方法届垫,可以指定軟鍵盤(pán)mode
                 .keyboardMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)  //單獨(dú)指定軟鍵盤(pán)模式
                 .setOnKeyboardListener(new OnKeyboardListener() {    //軟鍵盤(pán)監(jiān)聽(tīng)回調(diào),keyboardEnable為true才會(huì)回調(diào)此方法
                       @Override
                       public void onKeyboardChange(boolean isPopup, int keyboardHeight) {
                           LogUtils.e(isPopup);  //isPopup為true全释,軟鍵盤(pán)彈出装处,為false,軟鍵盤(pán)關(guān)閉
                       }
                  })
                 .setOnNavigationBarListener(onNavigationBarListener) //導(dǎo)航欄顯示隱藏監(jiān)聽(tīng)浸船,目前只支持華為和小米手機(jī)
                 .setOnBarListener(OnBarListener) //第一次調(diào)用和橫豎屏切換都會(huì)觸發(fā)妄迁,可以用來(lái)做劉海屏遮擋布局控件的問(wèn)題
                 .addTag("tag")  //給以上設(shè)置的參數(shù)打標(biāo)記
                 .getTag("tag")  //根據(jù)tag獲得沉浸式參數(shù)
                 .reset()  //重置所以沉浸式參數(shù)
                 .init();  //必須調(diào)用方可應(yīng)用以上所配置的參數(shù)

3、詳細(xì)介紹-解決狀態(tài)欄和布局頂部重合

上面已經(jīng)說(shuō)了李命,沉浸式原理就是使整個(gè)布局延伸到狀態(tài)欄和導(dǎo)航欄登淘,既然這樣必然導(dǎo)致一個(gè)問(wèn)題,就是狀態(tài)欄和布局頂部重疊项戴,直接看圖

圖片.png

眼神好的同學(xué)已經(jīng)看到上圖中給了五種解決方案啦形帮,在這里說(shuō)一下

  • 1 使用dimen自定義狀態(tài)欄高度
    在values-v19/dimens.xml文件下
    <dimen name="status_bar_height">25dp</dimen>

在values/dimens.xml文件下

    <dimen name="status_bar_height">0dp</dimen>

然后在布局界面添加view標(biāo)簽,高度指定為status_bar_height

   <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:background="@color/darker_gray"
       android:orientation="vertical">
   
       <View
           android:layout_width="match_parent"
           android:layout_height="@dimen/status_bar_height"
           android:background="@color/colorPrimary" />
   
       <android.support.v7.widget.Toolbar
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:background="@color/colorPrimary"
           app:title="方法一"
           app:titleTextColor="@android:color/white" />
   </LinearLayout>
  • 2 使用系統(tǒng)的fitsSystemWindows屬性

    在布局文件的根節(jié)點(diǎn)使用android:fitsSystemWindows="true"屬性

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:fitsSystemWindows="true">
    </LinearLayout>
然后使用ImmersionBar時(shí)候必須指定狀態(tài)欄顏色
    ImmersionBar.with(this)
         .statusBarColor(R.color.colorPrimary)
         .init();
  • 3 使用ImmersionBar的fitsSystemWindows(boolean fits)方法

    實(shí)現(xiàn)原理是獲得rootView的根節(jié)點(diǎn)周叮,然后設(shè)置距離頂部的padding值為狀態(tài)欄的高度值

    ImmersionBar.with(this)
        .statusBarColor(R.color.colorPrimary)
        .fitsSystemWindows(true)  //使用該屬性必須指定狀態(tài)欄的顏色,不然狀態(tài)欄透明界斜,很難看
        .init();
  • 4 使用ImmersionBar的statusBarView(View view)方法
    在標(biāo)題欄的上方增加View標(biāo)簽(也可以為其他標(biāo)簽)仿耽,高度指定為0dp
    <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:background="@color/darker_gray"
           android:orientation="vertical">
       
           <View
               android:layout_width="match_parent"
               android:layout_height="0dp"
               android:background="@color/colorPrimary" />
       
           <android.support.v7.widget.Toolbar
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:background="@color/colorPrimary"
               app:title="方法四"
               app:titleTextColor="@android:color/white" />
    </LinearLayout>

然后使用ImmersionBar的statusBarView方法,指定view就可以啦各薇,實(shí)現(xiàn)原理:ImmersionBar獲取狀態(tài)欄的高度项贺,傳入view,設(shè)置高度為獲取到的狀態(tài)欄高度

     ImmersionBar.with(this)
           .statusBarView(view)
           .init();
  • 5 使用ImmersionBar的titleBar(View view)方法
        ImmersionBar.with(this)
                  .titleBar(view) //指定標(biāo)題欄view
                  .init();

總結(jié):這五種方法峭判,任選其一使用就可以了开缎,不要一起使用哦,根據(jù)項(xiàng)目而定林螃,比如有側(cè)邊欄的奕删,建議使用第1種或者第4種或者第5種,最后來(lái)一張效果圖

圖片.png

4疗认、 在Fragment中實(shí)現(xiàn)沉浸式

在Fragment使用ImmersionBar

SimpleImmersionFragmentImmersionFragment區(qū)別是什么二蓝?

方法名字 SimpleImmersionFragment ImmersionFragment
initImmersionBar():沉浸式代碼寫(xiě)著這里 ? ?
immersionBarEnabled():當(dāng)前Fragment是否可以走initImmersionBar方法 ? ?
onLazyBeforeView():懶加載尊蚁,在view初始化之前調(diào)用 ? ?
onLazyAfterView():懶加載,在view初始化之后調(diào)用 ? ?
onVisible():當(dāng)前Fragment對(duì)用戶可見(jiàn)的時(shí)候調(diào)用 ? ?
onInvisible():當(dāng)前Fragment不可見(jiàn)的時(shí)候調(diào)用 ? ?
Fragment的切換侣夷,在Activity使用ImmersionBar
  • 第一種横朋,當(dāng)結(jié)合viewpager使用的時(shí)候,請(qǐng)使用viewpager的addOnPageChangeListener的方法監(jiān)聽(tīng)沉浸式百拓,參考demo中FragmentThreeActivity這個(gè)類
  • 第二種琴锭,當(dāng)使用show()和hide()來(lái)控制Fragment顯示隱藏的時(shí)候,請(qǐng)?jiān)趖ab切換的時(shí)候使用ImmersionBar衙传,參考demo中FragmentFourActivity這個(gè)類
使用Fragment第三方框架Fragmentation實(shí)現(xiàn)沉浸式
aaa.gif

5决帖、在Dialog中實(shí)現(xiàn)沉浸式,具體實(shí)現(xiàn)參考demo

在DialogFragment使用

   ImmersionBar.with(this, dialog).init();      

其他dialog蓖捶,關(guān)閉dialog的時(shí)候必須調(diào)用銷毀方法

       ImmersionBar.with(this, dialog).init();

銷毀方法:

java中

       ImmersionBar.destroy(this, mAlertDialog);

kotlin中

      destroyImmersionBar(mAlertDialog)
bbb.gif

6地回、在PopupWindow中實(shí)現(xiàn)沉浸式,具體實(shí)現(xiàn)參考demo

重點(diǎn)是調(diào)用以下方法俊鱼,但是此方法會(huì)導(dǎo)致有導(dǎo)航欄的手機(jī)底部布局會(huì)被導(dǎo)航欄覆蓋刻像,還有底部輸入框無(wú)法根據(jù)軟鍵盤(pán)彈出而彈出,具體適配請(qǐng)參考demo并闲。

    popupWindow.setClippingEnabled(false);
圖片狀態(tài)欄+彩色導(dǎo)航欄
 ImmersionBar.with(this)
         .transparentStatusBar()  //不寫(xiě)也可以细睡,默認(rèn)就是透明色
         .navigationBarColor(R.color.colorPrimary)
         .init();
ccc.jpg

7、全屏圖片

  ImmersionBar.with(this).transparentBar().init();
圖片.png

8帝火、 彩色狀態(tài)欄+彩色導(dǎo)航欄

       ImmersionBar.with(this)
                .statusBarColor(R.color.colorPrimary)
                .navigationBarColor(R.color.btn8)
                .init();
圖片.png

9溜徙、 修改狀態(tài)欄字體顏色為深色

       ImmersionBar.with(this).statusBarDarkFont(true).init();
圖片.png

10、 設(shè)置狀態(tài)欄和導(dǎo)航欄透明度

       ImmersionBar.with(this)
                .navigationBarColor(R.color.colorPrimary)
                .barAlpha(0.2f)
                .init();
圖片.png

11犀填、隱藏狀態(tài)欄

 ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_STATUS_BAR).init();

12蠢壹、隱藏導(dǎo)航欄

  ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_NAVIGATION_BAR).init();

13辽话、隱藏狀態(tài)欄+導(dǎo)航欄

  ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_BAR).init();

14串绩、 恢復(fù)狀態(tài)欄+導(dǎo)航欄

  ImmersionBar.with(this).hideBar(BarHide.FLAG_SHOW_BAR).init();

15、解決EditText和軟鍵盤(pán)的問(wèn)題

實(shí)現(xiàn)原理:監(jiān)聽(tīng)界面容器的layout變化云石,當(dāng)發(fā)生變化時(shí)比庄,通過(guò)檢查窗口可見(jiàn)區(qū)域高度求妹,判斷鍵盤(pán)是否彈起,如果彈起佳窑,則修改容器bottom padding制恍,也就是手動(dòng)實(shí)現(xiàn)adjustResize效果,給鍵盤(pán)留出顯示空間神凑。

   ImmersionBar.with(this)
               .keyboardEnable(true)  //解決軟鍵盤(pán)與底部輸入框沖突問(wèn)題
               .init();
       或者
       // KeyboardPatch.patch(this).enable();
       或者,layout指的是當(dāng)前布局的根節(jié)點(diǎn)
       // KeyboardPatch.patch(this, layout).enable();
eee.gif

16净神、 當(dāng)白色背景狀態(tài)欄遇到不能改變狀態(tài)欄字體為深色的設(shè)備時(shí)何吝,解決方案

        ImmersionBar.with(this)
                  .statusBarDarkFont(true, 0.2f)
                  .init();
圖片.png

17、清除導(dǎo)航欄高度鹃唯,布局到頂部

    //設(shè)置狀態(tài)欄
        ImmersionBar.with(this)
                .fitsSystemWindows(false)
                 //白色字體
                .statusBarDarkFont(false, 0.5f)
                .navigationBarColor(R.color.color_FFFFFF)
                .init();

注意:文字距離頂部距離爱榕,通過(guò)代碼控制。

如圖.png

四坡慌、源碼分析

本庫(kù)采用類似建造者模式來(lái)完成黔酥,只為了方便大家更靈活的去設(shè)置狀態(tài)欄和導(dǎo)航欄風(fēng)格。實(shí)現(xiàn)沉浸式是分為兩塊洪橘,一塊是android5.0以上跪者,一塊是android4.4,這兩塊實(shí)現(xiàn)原理完全不一樣熄求,在講解原理之前先看幾個(gè)概念渣玲,下面需要用到

  • View.SYSTEM_UI_FLAG_VISIBLE:顯示狀態(tài)欄,Activity不全屏顯示(恢復(fù)到有狀態(tài)的正常情況)弟晚。

  • View.INVISIBLE:隱藏狀態(tài)欄忘衍,同時(shí)Activity會(huì)伸展全屏顯示。

  • View.SYSTEM_UI_FLAG_FULLSCREEN:Activity全屏顯示卿城,且狀態(tài)欄被隱藏覆蓋掉枚钓。

  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:Activity全屏顯示,但狀態(tài)欄不會(huì)被隱藏覆蓋藻雪,狀態(tài)欄依然可見(jiàn)秘噪,Activity頂端布局部分會(huì)被狀態(tài)遮住。

  • View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:效果同-View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

  • View.SYSTEM_UI_LAYOUT_FLAGS:效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

  • View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:隱藏虛擬按鍵(導(dǎo)航欄)勉耀。有些手機(jī)會(huì)用虛擬按鍵來(lái)代替物理按鍵。

  • View.SYSTEM_UI_FLAG_LOW_PROFILE:狀態(tài)欄顯示處于低能顯示狀態(tài)(low profile模式)蹋偏,狀態(tài)欄上一些圖標(biāo)顯示會(huì)被隱藏便斥。

1、android 5.0以上核心代碼

Android自5.0起威始,為我們提供了設(shè)置狀態(tài)欄和導(dǎo)航欄顏色的API枢纠,我們可以自己設(shè)置狀態(tài)欄和導(dǎo)航欄的顏色。本框架在android5.0以上就是采用官方api完成的黎棠,網(wǎng)上關(guān)于5.0以上的實(shí)現(xiàn)基本都是這樣晋渺,在這里就不多說(shuō)了,在這里只說(shuō)一點(diǎn)脓斩,就是設(shè)置顏色的時(shí)候不是直接填入開(kāi)發(fā)者傳入的顏色值木西,而是采用v4包下的ColorUtils.blendARGB()方法來(lái)設(shè)置,為什么這樣設(shè)計(jì)呢随静?有些app的狀態(tài)欄并不是和標(biāo)題欄顏色相同八千,稍微有些色差吗讶,所以在這里開(kāi)發(fā)者只需要通過(guò)blendARGB()設(shè)置透明度就可以形成這種色差,而且還可以指定兩種顏色之間的色差值恋捆,方便大家照皆,android4.4上亦是如此。請(qǐng)看以下代碼:

       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                int uiFlags =View.SYSTEM_UI_FLAG_LAYOUT_STABLE   //防止系統(tǒng)欄隱藏時(shí)內(nèi)容區(qū)域大小發(fā)生變化 
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;  //Activity全屏顯示沸停,但狀態(tài)欄不會(huì)被隱藏覆蓋膜毁,狀態(tài)欄依然可見(jiàn),Activity頂端布局部分會(huì)被狀態(tài)欄遮住愤钾。
                if (mBarParams.fullScreen) {
                    uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; //Activity全屏顯示瘟滨,但導(dǎo)航欄不會(huì)被隱藏覆蓋,導(dǎo)航欄依然可見(jiàn)绰垂,Activity底部布局部分會(huì)被導(dǎo)航欄遮住室奏。
                }
                mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);  //取消設(shè)置透明狀態(tài)欄和導(dǎo)航欄
                mWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);  //需要設(shè)置這個(gè)才能設(shè)置狀態(tài)欄顏色
                mWindow.setStatusBarColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                        mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));  //設(shè)置狀態(tài)欄顏色
                mWindow.setNavigationBarColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
                        mBarParams.navigationBarColorTransform, mBarParams.navigationBarAlpha));  //設(shè)置導(dǎo)航欄顏色
                mWindow.getDecorView().setSystemUiVisibility(uiFlags); 把剛才設(shè)置的標(biāo)記通過(guò)setSystemUiVisibility方法設(shè)置進(jìn)去
            } 

2、 android 4.4核心代碼

在4.4里就沒(méi)有5.0以上這些api了劲装,只能設(shè)置透明狀態(tài)欄和導(dǎo)航欄胧沫,而且設(shè)置透明導(dǎo)航欄之后,底部布局會(huì)被導(dǎo)航欄遮住占业,那怎么辦呢绒怨?好吧,只能自己寫(xiě)代碼去實(shí)現(xiàn)啦谦疾。再說(shuō)之前南蹂,說(shuō)說(shuō)我的一個(gè)思路吧。現(xiàn)在是2.x.x版本念恍,在1.x.x版本的時(shí)候六剥,4.4中實(shí)現(xiàn)沉浸式是引用大家非常熟悉的一個(gè)庫(kù)SystemBarTint(不推薦使用了,很久沒(méi)人維護(hù)了)來(lái)實(shí)現(xiàn)的峰伙,但是后來(lái)發(fā)現(xiàn)一個(gè)嚴(yán)重的問(wèn)題疗疟,對(duì)于有導(dǎo)航欄的手機(jī),設(shè)置導(dǎo)航欄顏色的時(shí)候瞳氓,底部布局會(huì)被導(dǎo)航欄遮住策彤,除此之外還有一個(gè)小問(wèn)題就是當(dāng)用戶設(shè)置狀態(tài)欄為透明色的時(shí)候,不能時(shí)刻改變bar的顏色值匣摘,are you kidding店诗?既然出現(xiàn)這樣的問(wèn)題,就想著怎么去解決吧音榜!就這樣庞瘸,我乖乖去看看SystemBarTint的源代碼,哦囊咏!原理如此恕洲,發(fā)現(xiàn)SystemBarTint庫(kù)的實(shí)現(xiàn)就是在狀態(tài)欄和導(dǎo)航欄的位置自定義了可以改變背景顏色的view塔橡,然后通過(guò)window.getDecorView()得到根布局,把剛才創(chuàng)建的view添加進(jìn)去霜第,既然這樣葛家,為何不自己也寫(xiě)一個(gè),順便把剛才說(shuō)到導(dǎo)航欄的問(wèn)題也解決一下呢泌类。解決方法如下代碼癞谒,在這里通過(guò)注釋的方法向大家說(shuō)明。這里代碼只是片段刃榨,不可以直接拷貝到自己的項(xiàng)目中

       if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
            mWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明狀態(tài)欄
                mWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);//透明導(dǎo)航欄弹砚,設(shè)置這個(gè),如果有導(dǎo)航欄枢希,底部布局會(huì)被導(dǎo)航欄遮住
                setupStatusBarView(); //在根節(jié)點(diǎn)創(chuàng)建一個(gè)可以自定義顏色的狀態(tài)欄創(chuàng)建一個(gè)假的狀態(tài)欄
                if (mConfig.hasNavigtionBar())  //判斷是否存在導(dǎo)航欄
                    setupNavBarView();   //在根節(jié)點(diǎn)創(chuàng)建一個(gè)可以自定義顏色的導(dǎo)航欄
                // 解決android4.4有導(dǎo)航欄的情況下桌吃,activity底部被導(dǎo)航欄遮擋的問(wèn)題
                if (mConfig.hasNavigtionBar() && !mBarParams.fullScreenTemp && !mBarParams.fullScreen) {
                    if (mConfig.isNavigationAtBottom()) //判斷導(dǎo)航欄是否在底部
                        mContentView.setPadding(0, 0, 0, mConfig.getNavigationBarHeight()); //有導(dǎo)航欄,獲得當(dāng)前布局的根節(jié)點(diǎn)苞轿,然后設(shè)置距離底部的padding值為導(dǎo)航欄的高度值
                    else
                        mContentView.setPadding(0, 0, mConfig.getNavigationBarWidth(), 0); //不在底部茅诱,設(shè)置距離右邊的padding值為導(dǎo)航欄的寬度值
                } else {
                    mContentView.setPadding(0, 0, 0, 0); //沒(méi)有導(dǎo)航欄,什么都不做
                }
        }
/**
     * 在根節(jié)點(diǎn)創(chuàng)建一個(gè)可以自定義顏色的狀態(tài)欄
     */
    private void setupStatusBarView() {
        if (mBarParams.statusBarView == null) {
            mBarParams.statusBarView = new View(mActivity);//創(chuàng)建一個(gè)view
        }
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, getStatusBarHeight(mActivity));
        params.gravity = Gravity.TOP; //把view設(shè)置在頂部
        if (!isNavigationAtBottom(mActivity)) {
            params.rightMargin = getNavigationBarWidth(mActivity); //橫屏的時(shí)候搬卒,距離右邊的距離
        }
        mBarParams.statusBarView.setLayoutParams(params);
        mBarParams.statusBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));//設(shè)置view的顏色
        mBarParams.statusBarView.setVisibility(View.VISIBLE);
        ViewGroup viewGroup = (ViewGroup) mBarParams.statusBarView.getParent();
        if (viewGroup != null)
            viewGroup.removeView(mBarParams.statusBarView);
        mViewGroup.addView(mBarParams.statusBarView);
    }
/**
     * 在根節(jié)點(diǎn)創(chuàng)建一個(gè)可以自定義顏色的導(dǎo)航欄
     */
    private void setupNavBarView() {
        if (mBarParams.navigationBarView == null) {
            mBarParams.navigationBarView = new View(mActivity);  //創(chuàng)建一個(gè)view
        }
        FrameLayout.LayoutParams params;
        if (isNavigationAtBottom(mActivity)) { //判斷導(dǎo)航欄是否在底部
            params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, getNavigationBarHeight(mActivity));
            params.gravity = Gravity.BOTTOM; //如果在底部把view設(shè)置在導(dǎo)航欄的位置
        } else {
            params = new FrameLayout.LayoutParams(getNavigationBarWidth(mActivity), FrameLayout.LayoutParams.MATCH_PARENT);
            params.gravity = Gravity.END;  //不在底部瑟俭,把view設(shè)置到布局的結(jié)束位置
        }
        mBarParams.navigationBarView.setLayoutParams(params);
        if (!mBarParams.fullScreen && (mBarParams.navigationBarColorTransform == Color.TRANSPARENT)) {
            mBarParams.navigationBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
                    Color.BLACK, mBarParams.navigationBarAlpha));
        } else {
            mBarParams.navigationBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
                    mBarParams.navigationBarColorTransform, mBarParams.navigationBarAlpha));
        }
        mBarParams.navigationBarView.setVisibility(View.VISIBLE);
        ViewGroup viewGroup = (ViewGroup) mBarParams.navigationBarView.getParent();
        if (viewGroup != null)
            viewGroup.removeView(mBarParams.navigationBarView);
        mViewGroup.addView(mBarParams.navigationBarView);
    }

gitHub地址:https://github.com/gyf-dev/ImmersionBar
地址:https://p.codekk.com/detail/Android/gyf-dev/ImmersionBar
鏈接:http://www.reibang.com/p/2a884e211a62

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市契邀,隨后出現(xiàn)的幾起案子摆寄,更是在濱河造成了極大的恐慌,老刑警劉巖坯门,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件微饥,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡古戴,警方通過(guò)查閱死者的電腦和手機(jī)畜号,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)允瞧,“玉大人,你說(shuō)我怎么就攤上這事蛮拔∈鲈荩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵建炫,是天一觀的道長(zhǎng)畦韭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)肛跌,這世上最難降的妖魔是什么艺配? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任察郁,我火速辦了婚禮,結(jié)果婚禮上转唉,老公的妹妹穿的比我還像新娘皮钠。我一直安慰自己,他們只是感情好赠法,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布麦轰。 她就那樣靜靜地躺著,像睡著了一般砖织。 火紅的嫁衣襯著肌膚如雪款侵。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天侧纯,我揣著相機(jī)與錄音新锈,去河邊找鬼。 笑死眶熬,一個(gè)胖子當(dāng)著我的面吹牛妹笆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播聋涨,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼晾浴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了牍白?” 一聲冷哼從身側(cè)響起脊凰,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茂腥,沒(méi)想到半個(gè)月后狸涌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡最岗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年帕胆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片般渡。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡懒豹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出驯用,到底是詐尸還是另有隱情脸秽,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布蝴乔,位于F島的核電站记餐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏薇正。R本人自食惡果不足惜片酝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一囚衔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雕沿,春花似錦练湿、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至断国,卻和暖如春贤姆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背稳衬。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工霞捡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人薄疚。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓碧信,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親街夭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子砰碴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345