什么是沉浸式狀態欄
嚴格來說,沒有沉浸式狀態欄這種定義,谷歌dalao說的是** Immersive Mode **沉浸式模式(不過我個人叫的挺順口的,要改)。那么,什么是沉浸式模式呢?
首先理解一下我們的屏幕。大概是這樣:
我們常說的沉浸式表面上其實就是全屏模式。把導航欄、ActionBar、狀態欄都隱藏起來,就會達到一種沉浸式的體驗。
怎么使用
布局上沒什么特別的,讓你的內容 match_parent
填充滿布局就好,然后就是隱藏掉多余的東西。
怎么隱藏呢?
在 onCreate()的時候或者重寫方法** onWindowFocusChanged **,使用代碼 getWindow().getDecorView().setSystemUiVisibility(<View.屬性標簽>)
,把相應的屬性添加進去就基本搞定了。
這里列舉一下屬性標簽有什么:
- SYSTEM_UI_FLAG_FULLSCREEN: 隱藏狀態欄
- SYSTEM_UI_FLAG_HIDE_NAVIGATION: 隱藏導航欄
- SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: Activity全屏顯示,但是狀態欄不會被覆蓋掉,讓狀態欄上浮在Activity上
- SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: 讓導航欄懸浮在Activity上
- SYSTEM_UI_FLAG_LAYOUT_STABLE: 保持整個View的穩定,使其不會隨著SystemUI的變化而變化;
- SYSTEM_UI_FLAG_IMMERSIVE:沉浸模式;
- SYSTEM_UI_FLAG_IMMERSIVE_STICKY:沉浸模式且狀態欄和導航欄出現片刻后會自動隱藏;
看起來很多,我們來挑幾個重點的講一下。
IMMERSIVE 是 Android 4.4 ( API19 ) 引入的新標簽,當他和 FULLSCREEN、HIDE_NAVIGATION 一起引用時,會把導航欄和狀態欄一起隱藏,讓你的應用可以接受屏幕上任何地方的觸摸事件。實現真正的全屏模式。
還有比較特別說明的是 IMMERSIVE_STICKY 這個粘性標簽。就是沉浸模式下(比如你看小說或者視頻的時候),從狀態欄往內劃一下,狀態欄和導航欄就會顯示一會,再自動隱藏。
舉栗子
還是舉例子好明白,讓我們再來看一下這個例子。
沉浸模式(全屏體驗)
if ( Build.VERSION.SDK_INT >= 19) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
可能是我第三方模擬器的關系,我的導航欄并沒有顯示。但是我在我兩部真機上測試都是狀態欄和導航欄一起滑出來,大家可以測試一下。
加入的 LAYOUT_STABLE、LAYOUT_HIDE_NAVIGATION和LAYOUT_FULLSCREEN 屬性是為了穩定中間的 content 布局不變化(雖然我什么都沒加),中間的 content 可以放入 ImageView ,video 之類的東西。
如果想把狀態欄設置為透明,可以加上一句
getWindow().setStatusBarColor(Color.TRANSPARENT); //將狀態欄設置成透明色
。但是,只有 5.0 (API 21)及以上才支持
如何選擇一種沉浸模式
- 圖書,新聞等閱讀類應用
- IMMERSIVE 、FULLSCREEN 、HIDE_NAVIGATION
- 真正的沉浸式應用,屏幕的邊緣區域也可以和用戶進行交互(比如某些游戲)
- IMMERSIVE_STICKY、FULLSCREEN 、HIDE_NAVIGATION
- 視頻播放器
- FULLSCREEN 、HIDE_NAVIGATION 就夠了
補充說明
前面說要使用 setSystemUiVisibility 可以放在 onCreate() 里面,我再測試了一下,發現會有個問題。先貼我的代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 19) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
if (Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(Color.BLUE);
}
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
}
看圖解釋:
看圖可以發現,如果在 onCreate 里面使用這個方法隱藏了狀態欄和導航欄,但是當你按下 HOME 鍵后再返回這個 activity ,onCreate 方法是不會再調用的,他的狀態欄和導航欄將不再隱藏,也就是他的 UI flag 被清除掉了。這時你只能重新啟動這個activity,然而這是不符合需求的。
解決辦法:在 **onWindowFocusChanged ** 里面調用就好。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && Build.VERSION.SDK_INT >= 19) {//加了 hasFocus
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
參考資料: