android 狀態欄梳理

搞 android 很久了,狀態欄 StatusBar 也是時候徹底梳理下了,以前也是改過全屏,改過顏色,4.4 和 5.0 都有不同的處理,以前寫完就完了,現在回想起來已經不記得細節了,所以今天來梳理一下吧

本文涉及對 StatusBar 進行一下操作:

  • 改全屏,StatusBar 不顯示
  • 改全屏,StatusBar 顯示
  • StatusBar 透明
  • StatusBar 改顏色
  • StatusBar 改字體顏色

全屏,StatusBar 不顯示

這個我們在閃屏頁用,有4種寫法:

// 方法1 
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        
// 方法2
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
    <!-- 方法3 -->
    <style name="AppThemefullScreen" parent="AppTheme">
        <item name="android:windowFullscreen">true</item>
    </style>

    <!-- 方法4 -->
    android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"

這個好理解,就不展開了,有區別的是 方法2, 方法2 會生成一個狀態欄由顯示到隱藏的動畫,模擬器上跑的挺好,但是真機會卡頓,所以大家還是修改 window 的屬性吧,window 最優先顯示



狀態欄透明

其實在實際操作中,使用狀態欄透明的操作不多,而且都不是為了讓狀態欄去透明,而是奔著狀態欄在透明時會失去位置這個特性來,比如讓圖片延伸至標題欄

這里我們可以選擇 theme 或是代碼的方式,但是 theme 簡單不是

values/style.xml

<style name="ImageTranslucentTheme" parent="AppTheme">
    <!--在Android 4.4之前的版本上運行,直接跟隨系統主題-->
</style>

values-v19/style.xml

<style name="ImageTranslucentTheme" parent="AppTheme">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

values-v21/style.xml

<style name="ImageTranslucentTheme" parent="AppTheme">
    <item name="android:windowTranslucentStatus">false</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <!--Android 5.x開始需要把顏色設置透明,否則導航欄會呈現系統默認的淺灰色-->
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>
標準情況下樣子是這樣的:
5.1_1

5.1_2
4.4_1

4.2_2

從上面圖可以看到,狀態欄一旦透明了,就失去位置了,雖然還在,但是我們的內容 view 就占據狀態欄的位置了

注意啊:

  • activity 要是沒有背景色,那么狀態欄就是白色活透明的、
  • 5.0 時狀態欄顏色隨著 activity 背景色走,這個我測過了,就不上圖了
  • 4.4 時狀態欄顏色隨著 toolbar 背景色走
糾正狀態欄不占位的問題

這個就要用到 android:fitsSystemWindows="true" 這個屬性了

fitsSystemWindows 見名知意,意思是表示系統還是要占據狀態欄的位置了,這樣我們的狀態欄和 ui 才能沒有沖突

注意 fitsSystemWindows 需要設置在 layout 的跟視圖上

設置 android:fitsSystemWindows="true" 后,我們來看看:


5.1

4.4

這次 uI 就不占據 狀態爛 的位置了,image 圖也 跟著下來了,所以大家根據實際需求走

注意啊在 theme 設置 fitsSystemWindows ,會使所有的 view 都生效,這點在 toast 時有問題



修改狀態欄顏色

這點在 5.0 以后很簡單,兼容性也好

    <style name="AppThemeTranslucent" parent="AppTheme">
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowTranslucentNavigation">true</item>
        <item name="android:statusBarColor">@color/colorAccent</item>
    </style>

使用系統的 statusBarColor 參數就可以了

5.0 之后我們不改,系統狀態欄也會跟著 app 顏色色調走,大家看看 color 里面顏色對應的部分


但是在 4.4 就坑爹了,雖說 android 從 4.4 開始支持修改狀態欄顏色,但是在4.4 上實現很麻煩,還有兼容性問題,不確定所有的手機都好使

思路如下:

  • 先給設置 狀態欄 為透明
  • 再給 window -> DecorView -> ContentView 在第一個位置 添加一個 狀態欄 高度的 view 進來,內容 layout FitsSystemWindows 設為 true
    fun setStatusBarColor() {
        var window = getWindow()
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {

            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            var systemContent = findViewById(android.R.id.content) as ViewGroup

            var statusBarView = View(this)
            var lp = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(this))

            statusBarView.setBackgroundColor(getResources().getColor(R.color.colorAccent))

            systemContent.getChildAt(0).setFitsSystemWindows(true);
            systemContent.addView(statusBarView, 0, lp);
        }
    }

    fun getStatusBarHeight(context: Context): Int {
        var result: Int = 0
        var resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android")
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId)
        }
        return result;
    }

修改狀態欄文字顏色

這個是在 6.0 之后才提供的功能,說是可以修改顏色,其實也只是能把顏色改為暗顏色和亮顏色,說白了就是白色和黑色

除了官方 rom 外,魅族和 miui 和也可以改

  1. 官方 rom 實現:
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)}

// 白底黑字
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
// 黑絲白字
View.SYSTEM_UI_FLAG_LAYOUT_STABLE)

不設置的時候是白色字,設置上面之后就是黑色的字,大家想啊,亮的狀態欄那肯定得黑色文字才能看的清不是

經過測試,魅族手機官方 api 也慣用,大家在測試時,一定要和測試手機斷開之后才寫入程序才行,要不狀態欄不會生效,只有讓 app 重新啟動修改狀態欄的操作才能有效

  1. 魅族 rom 實現:

魅族官方提供了代碼,提供了一個類,大家下載下來,然后直接用就可以啦

地址: 魅族_狀態欄變色

  1. 小米 rom 實現:

小米也是一樣,不過小米提供的是一個 demo ,大家耐心點下下來看看

地址:MIUI 6 沉浸式狀態欄調用方法
地址:MIUI 9

最后網上有一些對官方原生,魅族,小米代碼的封裝,我試了試不生效,大家還是自己去看官放的代碼后自己測試有效后才自己封裝一下吧


如何統一修改 FitsSystemWindows

我們上面說了 FitsSystemWindows 要設置在 layout 根本布局,其實 window -> DecorView -> ContentView 更是根布局,給他設置 FitsSystemWindows 也是一樣,下面代理里的版本判斷大家根據自己需求執行更改

Window window = getWindow();
//默認API 最低19 
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    ViewGroup contentView = window.getDecorView().findViewById(Window.ID_ANDROID_CONTENT);
    contentView.getChildAt(0).setFitsSystemWindows(false);
}

擴展

  1. 使用CollapsingToolbarLayout使ToolBar具有折疊效果

效果的樣子就是上面的,我記得好像不用設置一大堆代碼就行,大家先按 layout 的思路走一遍,不行再上代碼

具體的大家請看下面這篇:

  1. 有人總結了些修改狀態欄后的 bug

劉海屏適配

國內的劉海屏時刻在太坑了,國內廠商早在 google 之前就用上了 劉海屏 ,所以 google 在 android p 28 上提供的方法就別想用了啦,沒戲,我們之只能挨個商家去適配...

這方面有非常好的文章,我就不復制了,大家直接看下面的資料把

google P 適配思路:

華為,小米,oppo,vivo 適配四思路


狀態欄,導航欄顯示原理

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。