Android狀態欄實現沉浸式模式

由於Android官方歷來沒有給出過沉浸式狀態欄這樣的命名,只有沉浸式模式(Immersive Mode)這種說法。而有些人在沒有徹底瞭解清楚沉浸模式究竟是什麼東西的狀況下,就張冠李戴地認爲一些系統提供的狀態欄操做就是沉浸式的,而且還起了一個沉浸式狀態欄的名字。java

好比以前就有一個QQ羣友問過我,像餓了麼這樣的沉浸式狀態欄效果該如何實現?android

 

 

這個效果其實就是讓背景圖片能夠利用系統狀態欄的空間,從而可以讓背景圖和狀態欄融爲一體。ide

本篇文章當中我會教你們如何實現這樣的效果,但這個真的不叫沉浸式狀態欄。所以,這算是一篇技術+普及的文章吧,講技術的同時也糾正一下你們以前錯誤的叫法。佈局

什麼是沉浸式?

先來分析一下叫錯的緣由吧,之因此不少人會叫錯,是由於根本就不瞭解沉浸式是什麼意思,而後就人云亦云跟着叫了。那麼沉浸式究竟是什麼意思呢?學習

根據百度百科上的定義,沉浸式就是要給用戶提供徹底沉浸的體驗,使用戶有一種置身於虛擬世界之中的感受。優化

好比說如今大熱的VR就是主打的沉浸式體驗。ui

那麼對應到Android操做系統上面,怎樣纔算是沉浸式體驗呢?這個可能在大多數狀況下都是用不到的,不過在玩遊戲或者看電影的時候就很是重要了。由於遊戲或者影視類的應用都但願能讓用戶徹底沉浸在其中,享受它們提供的娛樂內容,但若是這個時候在屏幕的上方還顯示一個系統狀態欄的話,可能就會讓用戶分分鐘產生跳戲的感受。spa

那麼咱們來看一下比較好的遊戲都是怎麼實現的,好比說海島奇兵:操作系統

 

 

海島奇兵的這種模式就是典型的沉浸式模式,它的整個屏幕中顯示都是遊戲的內容,沒有狀態欄也沒有導航欄,用戶玩遊戲的時候就能夠徹底沉浸在遊戲當中,而不會被一些系統的界面元素所打擾。設計

而後咱們再來看一下愛奇藝的實現:

 

 

一樣也是相似的,愛奇藝將整個屏幕做爲影視的展現區,用戶在看電影的時候眼中就只會有電影的內容,這樣就不會被其餘一些無關的東西所分心。

這纔是沉浸式模式的真正含義,而所謂的什麼沉浸式狀態欄純粹就是在瞎叫,徹底都沒搞懂「沉浸式」 這三個字是什麼意思。

不過雖然聽上去好像是很高大上的沉浸式效果,實際看上去貌似就是將內容全屏化了而已嘛。沒錯,Android沉浸式模式的本質就是全屏化,不過咱們今天的內容並不只限於此,由於還要實現餓了麼那樣的狀態欄效果。那麼下面咱們就開始來一步步學習吧。

隱藏狀態欄

一個Android應用程序的界面上實際上是有不少系統元素的,觀察下圖:

 

 

能夠看到,有狀態欄、ActionBar、導航欄等。而打造沉浸式模式的用戶體驗,就是要將這些系統元素所有隱藏,只留下主體內容部分。

好比說我如今新建了一個空項目,而後修改佈局文件中的代碼,在裏面加入一個ImageView,以下所示:

<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">

    <ImageView  android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/bg" android:scaleType="centerCrop" />

</RelativeLayout>
  • 1
  •  

這裏將ImageView的寬和高都設置成match_parent,讓圖片充滿屏幕。如今運行一下程序,效果以下圖所示。

 

 

若是你將圖片理解成遊戲或者電影界面的話,那這個體驗離沉浸式就差得太遠了,至少狀態欄和ActionBar得要隱藏起來了吧?不要緊,咱們一步步進行優化,而且在優化中學習。

隱藏狀態欄和ActionBar的方式在4.1系統之上和4.1系統之下仍是不同的,這裏我就不許備考慮4.1系統之下的兼容性了,由於過於老的系統根本就沒有提供沉浸式體驗的支持。

修改MainActivity中的代碼,以下所示:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(option);
        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();
    }
}

這裏先調用getWindow().getDecorView()方法獲取到了當前界面的DecorView,而後調用它的setSystemUiVisibility()方法來設置系統UI元素的可見性。其中,SYSTEM_UI_FLAG_FULLSCREEN表示全屏的意思,也就是會將狀態欄隱藏。另外,根據Android的設計建議,ActionBar是不該該獨立於狀態欄而單獨顯示的,所以狀態欄若是隱藏了,咱們同時也須要調用ActionBar的hide()方法將ActionBar也進行隱藏。

如今從新運行一下程序,效果以下圖所示。

 

 

這樣看上去就有點沉浸式效果的模樣了。

雖然說這纔是正統的沉浸式含義,但有些朋友可能想實現的就是餓了麼那樣的狀態欄效果,而不是直接把整個系統狀態欄給隱藏掉,那麼又該如何實現呢?

其實也很簡單,只須要藉助另一種UI Flag就能夠了,以下所示:

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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);
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

首先須要注意,餓了麼這樣的效果是隻有5.0及以上系統才支持,所以這裏先進行了一層if判斷,只有系統版本大於或等於5.0的時候纔會執行下面的代碼。

接下來咱們使用了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN和SYSTEM_UI_FLAG_LAYOUT_STABLE,注意兩個Flag必需要結合在一塊兒使用,表示會讓應用的主體內容佔用系統狀態欄的空間,最後再調用Window的setStatusBarColor()方法將狀態欄設置成透明色就能夠了。

如今從新運行一下代碼,效果以下圖所示。

 

 

能夠看到,相似於餓了麼的狀態欄效果就成功實現了。

再聲明一次,這種效果不叫沉浸式狀態欄,也徹底沒有沉浸式狀態欄這種說法,咱們估且能夠把它叫作透明狀態欄效果吧。

隱藏導航欄

如今咱們已經成功實現隱藏狀態欄的效果了,不過屏幕下方的導航欄還比較刺眼,接下來咱們就學習一下如何將導航欄也進行隱藏。

其實實現的原理都是同樣的,隱藏導航欄也就是使用了不一樣的UI Flag而已,修改MainActivity中的代碼,以下所示:

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(option);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

這裏咱們同時使用了SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN,這樣就能夠將狀態欄和導航欄同時隱藏了。如今從新運行一下程序,效果如圖所示。

 

 

此次看上去好像終因而徹底全屏化了,但其實上這離真正的沉浸式模式還差得比較遠,由於在這種模式下,咱們觸摸屏幕的任意位置都會退出全屏。

 

 

這顯然不是咱們想要的效果,所以這種模式的使用場景比較有限。

除了隱藏導航欄以外,咱們一樣也能夠實現和剛纔透明狀態欄相似的效果,製做一個透明導航欄:

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 21) {
    View decorView = getWindow().getDecorView();
    int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
    decorView.setSystemUiVisibility(option);
    getWindow().setNavigationBarColor(Color.TRANSPARENT);
    getWindow().setStatusBarColor(Color.TRANSPARENT);
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

這裏使用了SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,表示會讓應用的主體內容佔用系統導航欄的空間,而後又調用了setNavigationBarColor()方法將導航欄設置成透明色。如今從新運行一下程序,效果以下圖所示。

 

 

真正的沉浸式模式

雖然說沉浸式導航欄這個東西是被不少人誤叫的一種稱呼,但沉浸式模式的確是存在的。那麼咱們如何才能實現像海島奇兵以及愛奇藝那樣的沉浸式模式呢?

首先你應該肯定本身是否真的須要這個功能,由於除了像遊戲或者視頻軟件這類特殊的應用,大多數的應用程序都是用不到沉浸式模式的。

當你肯定要使用沉浸式模式,那麼只須要重寫Activity的onWindowFocusChanged()方法,而後加入以下邏輯便可:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= 19) {
            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

沉浸式模式的UI Flag就這些,也沒什麼好解釋的,若是你須要實現沉浸式模式,直接將上面的代碼複製過去就好了。須要注意的是,只有在Android 4.4及以上系統才支持沉浸式模式,所以這裏也是加入了if判斷。

另外,爲了讓咱們的界面看上去更像是遊戲,這裏我將MainActivity設置成了橫屏模式:

<activity android:name=".MainActivity" android:screenOrientation="landscape">
    ...
</activity>

這樣咱們就實現相似於海島奇兵和愛奇藝的沉浸式模式效果了,以下圖所示。

 

 

能夠看到,界面默認狀況下是全屏的,狀態欄和導航欄都不會顯示。而當咱們須要用到狀態欄或導航欄時,只須要在屏幕頂部向下拉,或者在屏幕右側向左拉,狀態欄和導航欄就會顯示出來,此時界面上任何元素的顯示或大小都不會受影響。過一段時間後若是沒有任何操做,狀態欄和導航欄又會自動隱藏起來,從新回到全屏狀態。

這就是最標準的沉浸式模式。

相關文章
相關標籤/搜索