一斥滤、前言:
自從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)欄
導(dǎo)航欄
二老充、依賴:
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)欄和布局頂部重疊项戴,直接看圖
眼神好的同學(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)一張效果圖
4疗认、 在Fragment中實(shí)現(xiàn)沉浸式
在Fragment使用ImmersionBar
- 第一種完残,你的Fragment直接繼承SimpleImmersionFragment或者ImmersionFragment類,在initImmersionBar方法中實(shí)現(xiàn)沉浸式代碼横漏,只有當(dāng)immersionBarEnabled返回為true才可以走initImmersionBar方法哦谨设,不過(guò)immersionBarEnabled默認(rèn)返回已經(jīng)為true了,如果當(dāng)前Fragment不想走沉浸式方法缎浇,請(qǐng)將immersionBarEnabled設(shè)置為false
- 第二種扎拣,如果你的Fragment不能繼承SimpleImmersionFragment或者ImmersionFragment類,請(qǐng)參考SimpleImmersionFragment實(shí)現(xiàn)SimpleImmersionOwner接口,或者參考ImmersionFragment實(shí)現(xiàn)ImmersionOwner接口
SimpleImmersionFragment和ImmersionFragment區(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)沉浸式
- 參考demo中FragmentFiveActivity和BaseFiveFragment這個(gè)類
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)
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();
7、全屏圖片
ImmersionBar.with(this).transparentBar().init();
8帝火、 彩色狀態(tài)欄+彩色導(dǎo)航欄
ImmersionBar.with(this)
.statusBarColor(R.color.colorPrimary)
.navigationBarColor(R.color.btn8)
.init();
9溜徙、 修改狀態(tài)欄字體顏色為深色
ImmersionBar.with(this).statusBarDarkFont(true).init();
10、 設(shè)置狀態(tài)欄和導(dǎo)航欄透明度
ImmersionBar.with(this)
.navigationBarColor(R.color.colorPrimary)
.barAlpha(0.2f)
.init();
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();
16净神、 當(dāng)白色背景狀態(tài)欄遇到不能改變狀態(tài)欄字體為深色的設(shè)備時(shí)何吝,解決方案
ImmersionBar.with(this)
.statusBarDarkFont(true, 0.2f)
.init();
17、清除導(dǎo)航欄高度鹃唯,布局到頂部
//設(shè)置狀態(tài)欄
ImmersionBar.with(this)
.fitsSystemWindows(false)
//白色字體
.statusBarDarkFont(false, 0.5f)
.navigationBarColor(R.color.color_FFFFFF)
.init();
注意:文字距離頂部距離爱榕,通過(guò)代碼控制。
四坡慌、源碼分析
本庫(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