Android 沉浸式狀態欄

什么是沉浸式狀態欄

嚴格來說,沒有沉浸式狀態欄這種定義,谷歌dalao說的是** Immersive Mode **沉浸式模式(不過我個人叫的挺順口的,要改)。那么,什么是沉浸式模式呢?

首先理解一下我們的屏幕。大概是這樣:

圖片.png

我們常說的沉浸式表面上其實就是全屏模式。把導航欄、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 ) 引入的新標簽,當他和 FULLSCREENHIDE_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);
        }
    
全屏.gif

可能是我第三方模擬器的關系,我的導航欄并沒有顯示。但是我在我兩部真機上測試都是狀態欄和導航欄一起滑出來,大家可以測試一下。

加入的 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();
}

看圖解釋:

API21.gif

看圖可以發現,如果在 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);
    }
}

參考資料:

  1. 郭神的博客 : http://blog.csdn.net/guolin_blog/article/details/51763825
  2. 谷歌的文檔 : https://developer.android.com/training/system-ui/immersive.htm
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容