Android 4.4之後狀態列和導航欄細節美化(沉浸式狀態列)
1. 簡介
其實標題我是打算叫“搶眼的沉浸式狀態列”,但是檢視多篇文章以及官方文件發現,雖然“沉浸式狀態列”這個名字已經爛大街並且只要一提到這個標籤大家都知道是一個什麼樣的效果,其實沉浸式並不是這樣理解的,檢視官方文件發現,Google定義的沉浸式模式是4.4帶來的新api——ImmersiveMode,進入沉浸式模式的Flag–>SYSTEM_UI_FLAG_IMMERSIVE_STICKY,進入沉浸式模式之後可以更好的提高使用者體驗,此時手機螢幕上隱藏了狀態列和導航欄,只顯示使用者最關心的主體內容,讓使用者完全沉浸其中,這就是正確的沉浸式,這裡我為了提高本文的點選量故意在標題後新增沉浸式標籤,哈哈。。。。。
2. 使用場景
正確的沉浸式使用場景其實很少,常用的使用場景如下:
- 平常app中第一次啟動的引導頁,還有程式的歡迎介面,這些頁面我們平時使用的一般都是全屏模式,設定一個全屏主題就ok了,其實這就是一種沉浸式模式。
- 遊戲ing,現在市面上的Android手遊幾乎全部是沉浸式模式。
- 目前很火的視訊播放器如愛奇藝、騰訊視訊等在播放視訊的時候都是沉浸式模式。
這裡以騰訊視訊播放器為例,相關截圖如下:
3. 空間利用(著重記錄狀態列)
狀態列是本篇博文的重中之重,Google在android 4.4 之後加入狀態列著色以及空間利用的api,也就是說在4.4之前是沒有該功能的,所以我們沒必要考慮之前的系統相容問題,但是4.4和5.0以及5.0+的狀態列著色也是有差別的。那麼今天我就以Google出的Material Design設計規範來統一實現4.4以後的系統狀態列著色問題。
1.空間利用:
相關Flag註釋:
1. SYSTEM_UI_FLAG_FULLSCREEN 全屏(隱藏狀態列) 2. SYSTEM_UI_FLAG_HIDE_NAVIGATION 隱藏導航欄(結合全屏Flag使用) 3. SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 主體佈局可以利用導航欄空間 4. SYSTEM_UI_FLAG_LAYOUT_STABLE 主體佈局可以利用狀態列空間 5. SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 全屏(配合3和4使用) 6. SYSTEM_UI_FLAG_IMMERSIVE_STICKY 真正的沉浸式模式
空間使用:
首先我們定義一個app樣式主題同時適配4.4+、5.x、5.x+系統:
- res/values/styles.xml
<resources>
<style name="BaseAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">#FF4081</item>
</style>
<style name="AppTheme" parent="@style/BaseAppTheme">
</style>
</resources>
- res/values-v19(如果沒有該資料夾請新建)
<resources>
<style name="AppTheme" parent="@style/BaseAppTheme">
這個屬性是4.4系統引入的,表示透明化狀態列
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
- res/value-v21
我起初是在6.0的真機上測試,主題佈局可以延伸利用到狀態列空間,但是setStatusBarColor去設定狀態列顏色怎麼也設定不上去,最後發現鴻神的文章有這樣一句話如下:
對於5.0由於提供了setStatusBarColor去設定狀態列顏色,但是這個方法不能在主題中設定windowTranslucentStatus屬性。所以要加以下主題設定,本人親測,問題搞定,
<resources>
<style name="AppTheme" parent="@style/BaseAppTheme"></style>
</resources>
因為該功能是5.0之後出來的,那麼首先判斷手機系統版本是否是大於5.0,那麼程式碼如下:
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
如果是4.4到5.0系統的話也還是需要適配的,那麼我們可以動態設定一個和狀態列高度和寬度相同的view然後add置主題佈局最上面,把他當成狀態列的背景就好了,或者更簡單的直接給我們的主題佈局paddingTop一個狀態列的高度就ok了。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
// 獲取主體父佈局例項
ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
View statusBarView = new View(activity);
// 設定view的寬度為 MATCH_PARENT,高度為狀態列高度
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
// 設定view的顏色(最好和toolBar顏色一致,看起來比較美觀也符合Material Design設計規範)
statusBarView.setBackgroundColor(color);
contentView.addView(statusBarView, lp);
}
2.專案效果展示:
4. 相關Q&A
Q 1. 常見底部四個tab切換Fragment頁面,加入第一個和第三個tab將狀態列著色為黑色,第二個和第四個tab將狀態列著色為透明色,這個時候切換頁面時第二個和第四個tab偶爾透明色失效變為黑色,什麼情況?
A 1. 首先檢查系統版本是否在4.4以上,其次檢查以上主題設定和程式碼邏輯是否編寫正確,如果一切都沒問題,最後檢查tab切換fragment時是用的replace()方法還是add()和hide() 結合使用,如果是replace()請改為add()方式試試。應該是可以解決此Q。
Q 2. 使用上面的方法只能將主體佈局延伸到狀態列的空間上,但無法將狀態列顏色透明化或者上色,如何解決?
A 2. 如果上述方法無法實現,可能是忘了設定API21的主題樣式,如果設定還是不行,則請嘗試下面這種粗暴的方法,
Window window = getWindow();
// 先清理狀態列和導航欄的狀態,然後強制顯示狀態列和導航欄並設定flag模式
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
// 重新新增flag
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// 設定狀態列顏色
window.setStatusBarColor(Color.TRANSPARENT);
微信公眾號搜尋“土土哥”可關注本人公眾號。也可微信掃一掃下方二維碼加關注。