固定导航栏android,Android 状态栏和导航栏的真终极解决方案
去年我寫過一篇文章,透明狀態(tài)欄和導航欄的終極解決方案,并在 Github 上開源了代碼,https://github.com/Zackratos/UltimateBar,其實在那之后,我一直對這個項目進行維護和更新,最近,我又用 kotlin 重構了代碼,并加入了一些新的功能,代碼改動比較大,特意寫篇文章介紹一下,希望這個庫能給做 Android 開發(fā)的同學帶來幫助。
舊版本的缺陷
事實上,這次重構之后已經(jīng)是 3.0 版本了,之前重構 2.0 版本的時候已經(jīng)有了大幅度的修改,但 2.0 版的重構主要是對代碼的優(yōu)化,方便開發(fā)者的調用,比如采用 Builder 模式進行配置參數(shù)。而這次的重構,在功能上做了很大的修改,可以適用于更多的場景。
舊版本主要有 3 個缺陷。
參數(shù)過多。舊版本中設置狀態(tài)欄和導航欄的顏色的時候,參數(shù)包括了色值和透明度以及顏色的深度,導致調用的時候需要傳入大量的參數(shù),其實這些完全沒必要,透明度和顏色深度都是可以包含在色值里面的,嚴格來說,只要傳入一個參數(shù)就好了,至于它的透明度和深度,如果需要,開發(fā)者可以自己設置好之后再傳入。
同一個 Activity 只能設置一次。舊版本中一般需要使用透明狀態(tài)欄和導航欄的時候,都是在 onCreate 中設置,然后就固定了,但是如果有時候需要在 Activity 中再次設置不同的效果,就會力不從心了。
不支持灰色模式。我們知道, Android 6.0 以上是支持狀態(tài)欄灰色模式的,就是把狀態(tài)欄種的字體顏色改為灰色,這種模式是為了避免在白色界面上設置沉浸狀態(tài)欄導致狀態(tài)欄的字體看不見的尷尬的,但是舊版本中并沒有對這種情況進行適配。
新版本的改進
針對舊版本的缺陷,新版本主要做了以下改進。
去除多余的參數(shù)。新版本中狀態(tài)欄和導航欄的背景都只需要一個參數(shù),參數(shù)類型是 Drawable,相對于 Color 來說,Drawable 明顯更加靈活,不但可以設置狀態(tài)欄和導航欄的顏色,而且可以設置透明度,還有漸變色等各種效果,也就是說,只要是 Drawable 能實現(xiàn)的效果,都能設置到狀態(tài)欄和導航欄上。
支持多次設置。新版本中調整了代碼的邏輯,現(xiàn)在可以對狀態(tài)欄和導航欄的效果進行多次設置了,但是 UltimateBar 有四種效果,多次設置只能對同一種效果有效。比如說,如果你第一次設置了半透明的狀態(tài)欄和導航欄,那么后面要修改,也只能設置半透明的效果,如果設置其他效果會出現(xiàn)不可預知的問題。
支持灰色模式,分別對 Android 6.0 以上和 Android 8.0 以上適配了狀態(tài)欄灰色模式和導航欄灰色模式,避免白色界面狀態(tài)欄字體看不見的尷尬。
使用
UltimateBar 的使用非常簡單,首先在 gradle 中添加依賴
implementation 'com.github.zackratos.ultimatebar:ultimatebar3:3.0.0'
如果你要直接給狀態(tài)欄和導航欄設置一個背景,在 onCreate 中
UltimateBar.Companion.with(this)
.statusDark(false) // 狀態(tài)欄灰色模式(Android 6.0+),默認 flase
.statusDrawable(drawable) // 狀態(tài)欄背景,默認 null
.applyNavigation(true) // 應用到導航欄,默認 flase
.navigationDark(false) // 導航欄灰色模式(Android 8.0+),默認 false
.navigationDrawable(drawable) // 導航欄背景,默認 null
.create()
.drawableBar();
如果要給狀態(tài)欄和導航欄設置半透明效果,在 onCreate 中
UltimateBar.Companion.with(this)
.statusDark(false) // 狀態(tài)欄灰色模式(Android 6.0+),默認 flase
.statusDrawable(drawable) // 狀態(tài)欄背景,默認 null
.applyNavigation(true) // 應用到導航欄,默認 flase
.navigationDark(false) // 導航欄灰色模式(Android 8.0+),默認 false
.navigationDrawable(drawable) // 導航欄背景,默認 null
.create()
.transparentBar();
注意這里的 statusDrawable 和 navigationDrawable 的參數(shù)必須是半透明的,因為此時 contentView 會延伸到狀態(tài)欄和導航欄上面,如果不是半透明的,會把 contentView 蓋住。
如果要設置沉浸式狀態(tài)欄和導航欄,在 onCreate 中
UltimateBar.Companion.with(this)
.statusDark(false) // 狀態(tài)欄灰色模式(Android 6.0+),默認 flase
.applyNavigation(true) // 應用到導航欄,默認 flase
.navigationDark(false) // 導航欄灰色模式(Android 8.0+),默認 false
.create()
.immersionBar();
其實這就是第二種效果的特殊情況,即 statusDrawable 和 navigationDrawable 都為 null。
如果要隱藏狀態(tài)欄和導航欄,需要重寫 onWindowFocusChanged 方法
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
UltimateBar.Companion.with(this)
.applyNavigation(true) // 是否應用到導航欄
.create()
.hideBar();
}
}
如果使用了 DrawerLayout,需要實現(xiàn) DrawerLayout 的主布局被覆蓋,而抽屜需要沉浸的效果,可以在 onCreate 中
UltimateBar.Companion.with(this)
.statusDark(false) // 狀態(tài)欄灰色模式(Android 6.0+),默認 flase
.statusDrawable(drawable) // 狀態(tài)欄背景,默認 null
.applyNavigation(true) // 應用到導航欄,默認 flase
.navigationDark(false) // 導航欄灰色模式(Android 8.0+),默認 false
.navigationDrawable(drawable) // 導航欄背景,默認 null
.create()
.drawableBarDrawer(drawerLayout, // DrawerLayout
content, // DrawerLayout 的主布局 View
drawer); // DrawerLayout 的抽屜布局 View
以上所有的方法,如果是在 kotlin 中使用,都可以省略 Companion 關鍵詞,并且 kotlin 中可以用如下方式調用
with().statusDark(false) // 狀態(tài)欄灰色模式(Android 6.0+),默認 flase
.statusDrawable(drawable) // 狀態(tài)欄背景,默認 null
.applyNavigation(true) // 應用到導航欄,默認 flase
.navigationDark(false) // 導航欄灰色模式(Android 8.0+),默認 false
.navigationDrawable(drawable) // 導航欄背景,默認 null
.create()
.drawableBar();
with() 就相當于 UltimateBar.Companion.with(this)。
如果要在 Fragment 中使用,可以先設置 Fragment 所在的 Activity 沉浸,然后再設置 Fragment, 可以參考 demo 中的寫法。
終極方案
在實際開發(fā)中,有時會遇到一些奇葩的需求,各種復雜的情況疊加,這時候可以采用終極解決方案,就是先把狀態(tài)欄和導航欄都設置為沉浸式,然后通過在狀態(tài)欄和導航欄的位置加一個自定義背景的 View 和應對復雜的業(yè)務場景,具體使用可參考 demo。
簡單原理
狀態(tài)欄和導航欄的主要難點是 Android 4.4 和 Android 5.0 以上的實現(xiàn)方法不一樣,要達到一致的效果,必須進行版本適配。
在 Android 4.4 上只能設置狀態(tài)欄和導航欄透明,如果要設置它們的背景,必須在狀態(tài)欄和導航欄的位置手動添加一個 View,并設置 View 的背景來充當狀態(tài)欄和導航欄的背景,而在 Android 5.0 以上,可以直接設置狀態(tài)欄和導航欄的背景色。
但是在 Android 5.0 以上的 Api 中,狀態(tài)欄和導航欄的背景只能設置為 Color,不能是 Drawable,為了設置 Drawable,在 Android 5.0 以上,同樣先設置狀態(tài)欄和導航欄透明,然后也在狀態(tài)欄和導航欄的位置上添加一個 View,用 View 的背景來充當狀態(tài)欄和導航欄的背景,從而可以直接設置為 Drawable。
為什么不把狀態(tài)欄和導航欄分開設置
其實在重構 2.0 版本的時候,我就考慮把狀態(tài)欄和導航欄分開,分別設置,互不影響,這樣代碼更優(yōu)雅,調用起來也更方便,但是后來發(fā)現(xiàn)一個問題,就是導航欄不能單獨設置,如果單獨設置了導航欄沉浸,狀態(tài)欄也會出現(xiàn)沉浸的效果。但是可以單獨設置狀態(tài)欄沉浸,導航欄保持原狀,基于此原因,UltimateBar 設計為統(tǒng)一的 Api,然后通過參數(shù) applyNavigation 來確定要不要應用到導航欄中。
不過我現(xiàn)在又想到一個分開設置的野路子方法,就是每種情況都先設置成沉浸的效果,然后通過修改 mContentParent 的 paddingTop 和 paddingBottom 來設置狀態(tài)欄和導航欄的效果,這樣就可以把狀態(tài)欄和導航欄分開來設置了,可以考慮在下個版本中使用這種方法。
存在的不足
目前 UltimateBar 還存在以下幾點不足。
前面提到的,多次設置只能針對同一種效果,不同效果會有不可預估的問題,不過絕大多數(shù)情況下不會有這樣的需求。
也是前面提到的,狀態(tài)欄和導航欄沒有分開設置,現(xiàn)在只能單獨設置狀態(tài)欄或者同時設置狀態(tài)欄和導航欄,不能單獨設置導航欄,不過絕大多數(shù)情況不會有單獨設置導航欄這種奇葩的需求。
現(xiàn)在的狀態(tài)欄灰色模式只支持 Android 6.0 以上,因為官方是 Android 6.0 才開始支持的,但其實 miui 和 flyme 從 Android 4.4 就開始支持了,但是由于我身邊沒有相應的設備,不好測試,所以暫時沒有針對 miui 和 flyme 做專門的適配。
以上三點不足,其實都影響不大,之所以稱它們?yōu)椤安蛔恪?#xff0c;而不是“問題”,就是因為影響很小,不夸張的說,UltimateBar 絕對可以滿足絕大多數(shù)需求。
最后,奉上 Github 地址
歡迎 star、fork,提 issue、pull request。
總結
以上是生活随笔為你收集整理的固定导航栏android,Android 状态栏和导航栏的真终极解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言树形文件结构的创建,C语言二叉树
- 下一篇: android 自定义屏保,androi