關於 Android 狀態列的適配總結

sydMobile發表於2019-05-12

1.要求狀態列透明,我們的內容佈局延伸到系統狀態列,就是人們口中說的沉浸式狀態列:

Android 5.0 及其以後版本:設定屬性 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 使得我們的內容佈局可以延伸到系統狀態列,然後直接使用方法 setStatusBarColor() 把系統狀態列設定成透明就好了。

Android 4.4 ~ Android 5.0 :新增了屬性 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) 可以讓狀態列變成透明,並且使我們們的內容佈局延伸到系統狀態列。這個屬性雖然也可以在 Android 5.0 及其以後版本的手機上使用,但是效果不是我們想要的。

在 Android 4.4 之前是不支援透明狀態列

需要注意的一點是在設定透明狀態列的情況下,是需要我們的內容佈局延伸到狀態列的,因此這個時候使用 fitSystemWindows 這個屬性是沒有意義的,只會使得出現各種奇葩的效果。

2.狀態列顏色和我們佈局顏色搭配

其實在有的時候,我們是不需要把我們的內容佈局延伸到系統狀態列的,只是需要系統狀態列和我們的內容佈局的顏色搭配起來。

**Android 5.0 及其以後版本:**直接通過 setStatusBarColor() 或者 修改colorPrimaryDark 對應的顏色,把系統狀態列顏色設定成搭配的顏色就可以了

**Android 4.4 ~ Android 5.0:**這個版本其實是不允許直接修改狀態列的顏色的,只不過我們利用了一種巧妙的方法,感覺是修改了狀態列的顏色而已。通過 getWindow().addFlags(WindowManager.LayoutParams.FALG_TRANSLUCENT_STATUS) 是狀態列透明,並且我們的佈局也會延伸到狀態列,給我們的內容佈局設定一個 padding,給這個 padding 設定一個合適的顏色來充當系統狀態列的顏色就可以了。

Android 4.4 之前是不支援修改的

其實狀態列的適配無外乎這兩點了,注意一定要針對不同的 Android 版本使用不同的方法,不可亂用,不可混用,不然會有各種奇葩效果!

效果圖

Android 4.4 以前

狀態列永遠是黑底白字,沒有方法改變。上面的所有的方法也是不適用的。

Android4.4以下.png

Android 4.4~Android 5.0

Android 4.4 引入了 FLAG_TRANSLUCENT_STATUS 這種模式,使用這種模式可以使內容佈局佔據狀態列,效果:

Android4.4透明no.png

android:fitsSystemWindows = "true" 屬性
可以理解為給所使用的佈局設定了狀態列大小的 padding。只會作用於 Toolbar 和 根佈局。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:background="@color/main_green_00b661"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
<!--    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tb"
        app:title="@string/activity_status_bar"
        app:titleTextColor="@android:color/white"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        android:background="@color/colorAccent">
    </android.support.v7.widget.Toolbar>-->
    <TextView
        android:fitsSystemWindows="true"
        android:background="@color/main_green_00b661"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:text="11"
        android:textColor="#000"/>
    <ImageView
        android:contentDescription="@string/text_input"
        android:id="@+id/iv"
        android:scaleType="fitXY"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:src="@mipmap/imga"/>
    <TextView
        android:background="@color/colorAccent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="11"
        android:textColor="#000"/>
</LinearLayout>

比如,佈局是這樣的,fitsSystemWindows 只有在根佈局 LinearLayout 或者 ToolBar 上有用,在別的 View 上使用是沒有效果的。
複製程式碼

LinearLayout 使用 fitsSystemWindows

Android4.4透明toolbar-yes.png

ToolBar 設定 fitsSystemWindows 效果

Android4.4透明toolbar-yes.png

可以看到效果了。其實就是相當於給佈局設定了 padding top(高度相當於系統狀態列的高度),但是考慮到相容性的問題,如果你直接在佈局中設定 paddingtop 而不是通過 FitsSystemWindows 這個屬性,那麼在 Android 4.4 以下的手機上執行的話,那麼效果就很糟糕了,因為 Android 4.4 以下的手機,系統狀態列都是始終存在的,也就是說,這樣始終比 Android 4.4 以上系統的手機佈局多一塊 padding ,因為這一塊 padding 沒法在系統狀態列上。但是使用 fitsSystemWindo 就會完美適配了,因為這個屬性在 Android 4.4 以下的系統上是不起作用的。注意在使用 fitsSystemWindow 的時候,顏色問題,不同的手機系統,可能會造成延伸到狀態列的那一塊顏色不同,理論上顏色應該和根佈局的顏色一樣。

Android 5.0

到了 Android 5.0 關於狀態列又發生了變化,新增了直接對狀態列的操作,直接改變狀態列顏色,這一點在之前版本是沒有的,Android 4.4 雖然可以實現改變狀態列顏色的效果,但其實實際上是將我們的佈局佔據了狀態列,然後狀態列是透明的。其實顏色還是我們佈局的顏色。

對 Android 5.0 的採取

getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); (和上面對 Android 4.4 的方法是一樣的);
複製程式碼

效果圖:

Android5.0透明no.png

Android 6.0

在 Android 6.0 新增了可以更改狀態列字型顏色的方法,別的都是和 Android 5.0 一樣的。

狀態列字型顏色預設是白色。可以修改為黑色。

方法:getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

// 方法
/*
* 當 insets 檢視插入,window 已經更改了,檢視層次結構呼叫。允許它調整內容來適應這些視窗。這個 insets 會告訴我們 status bar、input method 和其他系統 window 的空間。

通常情況下我們是不需要處理此功能的,因為應用程式的預設視窗修飾會將其應用於視窗內容。如果我們使用 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 或者 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 的時候,則需要處理這個函式了,這個時候如果我們不處理,我們的檢視內容就會預設放在系統檢視的下面。如果我們希望系統檢視不覆蓋UI的某些部分,則可以在檢視層次結構中使用此方法。
預設情況下,只是將 insets(將 insets 設定為 0 )做為 View 的 padding。並且返回true。預設情況下,此行為是關閉的,但是可以通過 setFitsSystemWindows(boolean)啟用。

此功能在層次結構中的遍歷是深度優先的。 相同的內容insets物件沿著層次結構向下傳播,因此對其所做的任何更改都將被所有後續檢視看到(包括層次結構中的上層檢視,因為這是深度優先遍歷)。 返回true的第一個檢視將中止整個遍歷。

*/
fitSystemWindows(Rect insets);
複製程式碼

歡迎大家關注我的微信公眾號,和我交流分享

相關文章