Android笔记本Material Design

Android 沉浸式状态栏的实现

2018-12-06  本文已影响33人  骚年一起奋斗吧

沉浸式到底是一种什么感觉呢?

用户完全沉浸的体验,使用户有一种置身于虚拟世界之中的感觉。

我真的很难理解这是一种什么感觉。。。。

直到读了一下郭霖大神的Android状态栏微技巧,带你真正理解沉浸式模式,才有了一点点感觉啊(所以这篇文章是在郭霖博客上加了一些东西,为了让自己的知识更加巩固)。对,就是玩游戏的时候,我们都想置身于那种玩游戏的快感,突然来个系统状态栏的话,我觉着我反正是受不了的,都想砸手机的感觉。

总之,重要的事情说三遍

Android沉浸式模式的本质就是全屏化

Android沉浸式模式的本质就是全屏化

Android沉浸式模式的本质就是全屏化

下面,看一下,手机界面的系统元素有哪些

手机界面元素

而沉浸式模式就是要将这三个隐藏,我们需要注意的是,在android4.4之前,我们是没有办法设置状态栏的,4.4(API19)之后才会有这种沉浸式。

实现

1、通过设置Theme主题来设置状态栏和导航栏的透明度

这里,我们需要注意

Android5.0(API21)以上的状态栏,会有一层变透明的遮罩。
Android4.4(API19)以下的状态栏,默认会是黑色的
Android4.4至Android5.0的状态栏,会是全透明的

故,我们在设置的时候,需要三份styles.xml文件

styles文件

package: res/values/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

  <!--引入透明主题-->
    <style name="TranslucentTheme" parent="AppTheme"/>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        //标题栏的背景颜色
        <item name="colorPrimary">@color/colorPrimary</item>
        //状态栏的背景颜色
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        //各个控件被选中时候的颜色
        <item name="colorAccent">@color/colorAccent</item>
        //底部导航栏颜色
        <item name="android:navigationBarColor">@color/navigationColor</item>
        //toolbar的title颜色
        <item name="android:textColorPrimary">@color/textColorPrimary</item>
        //各个控件的默认颜色
        <item name="android:colorControlNormal">@color/colorControlNormal</item> 
    </style>

package: res/values-19/styles.xml 开始有 android:windowTranslucentStatus 这个属性

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!--android4.4开始有这个windowTranslucentStatus属性以上-->
    <style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!--状态栏透明-->
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
        
        <item name="android:fitsSystemWindows">true</item>
    </style>
</resources>

上面,我们看到设置了fitsSystemWindow的属性。这个属性简单的来说,我们在设置应用布局的时候是否需要考虑系统窗口(状态栏、导航栏、输入法等)布局。对于状态栏来自动添加paddingTop,导航栏自动添加paddingBottom

package: res/values-21/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>

        <!--让View根据系统窗口来调整自己的布局-->
        <item name="android:fitsSystemWindows">true</item>

        <!--Android 5.x开始需要把颜色设置为透明,否则导航栏会呈现系统默认的浅灰色-->
        <item name="android:statusBarColor">@android:color/transparent</item>

    </style>
</resources>

因为在5.0是半透明的,所以设置android:statusBarColor属性为透明的即可

效果图如下


2、java代码设置

修改MainActivity.java

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元素的可见性,View.SYSTEM_UI_FLAG_FULLSCREEN表示全屏的意思,也就是将状态栏隐藏。而且根据Android的设计建议,ActionBar的是不应该独立于状态栏而单独显示的,因此状态栏隐藏了,我们也要将ActionBar通过hide()方法进行隐藏。

运行程序,效果可见:


现在总结一下,option具体有哪些值

Flag 意义
SYSTEM_UI_FLAG_LOW_PROFILE 弱化状态栏和导航栏的图标
SYSTEM_UI_FLAG_HIDE_NAVIGATION 隐藏导航栏,用户点击屏幕会显示导航栏
SYSTEM_UI_FLAG_FULLSCREEN 隐藏状态栏
SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 拓展布局到导航栏后面
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 拓展布局到状态栏后面
SYSTEM_UI_FLAG_LAYOUT_STABLE 稳定的布局,不会随系统栏的隐藏、显示而变化
SYSTEM_UI_FLAG_IMMERSIVE 沉浸模式,用户可以交互的界面
SYSTEM_UI_FLAG_IMMERSIVE_STICKY 沉浸模式,用户可以交互的界面。同时,用户上下拉系统栏时,会自动隐藏系统栏

在Android5.0的机型上运行之后,显示的效果并不是我们xml设置出来的效果一样,也就是上面的状态栏没有了?不要慌,这是因为我们没有设置setStatusBarColor()状态栏为透明以及Flag为以下这种模式

SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 拓展布局到状态栏后面
SYSTEM_UI_FLAG_LAYOUT_STABLE 稳定的布局,不会随系统栏的隐藏、显示而变化

实现代码如下

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
   if (Build.VERSION.SDK_INT >= 21) { //5.0的机型上
    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();
     }
}

以上的方式其实并不是沉浸式状态栏,我们估且可以把它叫做透明状态栏效果吧。

上面的方式已经将状态栏,标题栏去除了。那么如何设置下面的导航栏呢?其实也很简单,我们修改一下option里面的FLAG即可

具体代码如下

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
   if (Build.VERSION.SDK_INT >= 21) { //5.0的机型上
    View decorView = getWindow().getDecorView();
    int option = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_FULLSCREEN;
    decorView.setSystemUiVisibility(option);
    getWindow().setStatusBarColor(Color.TRANSPARENT);
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
     }
}

运行之后,效果如下

现在看起来,效果不错。但是我们发现在这种模式下,我们触摸屏幕的任意位置的时候都会退出全屏

这显然不是我们想要的效果,因此,得实现一个真正的沉浸式模式

这时我们要重写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); //沉浸模式,用户可以交互的界面。同时,用户上下拉系统栏时,会自动隐藏系统栏
        }
    }

}

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

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

上一篇下一篇

猜你喜欢

热点阅读