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>

这样咱们就实现相似于海岛奇兵和爱奇艺的沉浸式模式效果了,以下图所示。

 

 

能够看到,界面默认状况下是全屏的,状态栏和导航栏都不会显示。而当咱们须要用到状态栏或导航栏时,只须要在屏幕顶部向下拉,或者在屏幕右侧向左拉,状态栏和导航栏就会显示出来,此时界面上任何元素的显示或大小都不会受影响。过一段时间后若是没有任何操做,状态栏和导航栏又会自动隐藏起来,从新回到全屏状态。

这就是最标准的沉浸式模式。

相关文章
相关标签/搜索