其它androidAndroid之界面

“沉浸式状态栏”--完全理解沉浸模式

2017-02-22  本文已影响723人  ifjgm

关于沉浸式状态栏一词的说法从何而来我们无从考证。但这确实是个错误的说法
先引用官方的一段话。

Immersive full-screen mode
To provide your app with a layout that fills the entire screen, the new SYSTEM_UI_FLAG_IMMERSIVE flag for setSystemUiVisibility()(when combined with SYSTEM_UI_FLAG_HIDE_NAVIGATION enables a new immersivefull-screen mode. While immersive full-screen mode is enabled, your activity continues to receive all touch events. The user can reveal the system bars with an inward swipe along the region where the system bars normally appear. This clears the SYSTEM_UI_FLAG_HIDE_NAVIGATION flag (and the SYSTEM_UI_FLAG_FULLSCREEN flag, if applied) so the system bars remain visible. However, if you'd like the system bars to hide again after a few moments, you can instead use the SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag.

Translucent system bars

You can now make the system bars partially translucent with new themes, Theme.Holo.NoActionBar.TranslucentDecor and Theme.Holo.Light.NoActionBar.TranslucentDecor.By enabling translucent system bars, your layout will fill the area behind the system bars, so you must also enable fitsSystemWindows for the portion of your layout that should not be covered by the system bars.
If you're creating a custom theme, set one of these themes as the parent theme or include the windowTranslucentNavigation and windowTranslucentStatus style properties in your theme.

以上是官网对于状态栏的相关描述。那么什么意思呢?

沉浸式全屏模式:activity 占据整个屏幕,用户交互时(拖动状态栏所在的位置)才会出现状态栏和导航栏

沉浸全屏模式
透明状态栏模式:状态栏和导航栏依然可见但是呈现半透明状态
透明状态栏模式
注意:以上效果是在原生开发系统上的效果,部分国产定制系统可能略有差异。请注意

实现方式:

其一Translucent Bar是4.4开始有的特性;其二是5.0开始,Google推出Material Design,使用Theme.Material(MD主题)或Theme.AppCompat主题并至少设置ColorPrimaryDark属性就可以实现status bar半透明效果,所以本文只讨论API19以上操作系统

  1. 通过Theme 方式实现,官网有说明android 中文官网
 <style name="translusent"parent="android:Theme.Holo.Light.NoActionBar.TranlucentDecor">
</style>

在AndroidManifest 中设置使用该theme

<activity
     android:name=".translucent.TranslusentThemeActivity"
     android:label="@string/translucent_theme"
     android:theme="@style/translusent">
 </activity>
<style name="translusent" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="android:windowTranslucentStatus">true</item>
  <item name="android:windowTranslucentNavigation">true</item>
  </style>

由于 5.x开始需要把颜色设置透明 ,所以我们必须新建个values-v21,并新建下面的主题

<style name="translusent" parent="Theme.AppCompat.Light.DarkActionBar">
 <item name="android:windowTranslucentStatus">true</item>
 <item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
 <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->   
    </style>
总结:由主题来实现有一定的不确定性(少数情况下),可能因为定制机器。模拟器等原因而达不到预期效果。但也不失为一种简单方便的实现方式
  1. 通过java代码实现。下面我逐步实现
    首先我们看下整体的代码
public class TranslusentActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.translucent);
        /**
         * 由于21以下不能设置statusbar和NavigationBar的颜色所以实现透明化系统栏效果,仍然可以实现沉浸全屏模式
         * */
        if (Build.VERSION.SDK_INT >= 21) {
            int option = getOption(6);
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(option);

            getWindow().setStatusBarColor(Color.TRANSPARENT);//设置statusbar为透明色
            getWindow().setNavigationBarColor(Color.TRANSPARENT);//设置NavigationBar为透明色
        }
        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();
    }
    /**
     * 由于各个flag都有相互制约性,不是单纯的相互叠加效果。
     * 所以也不必再在意每个flag的作用
     *
     * */
    private int getOption(int type) {
        int option = 0;
        switch (type) {
            case 0:
                //隐藏statusbar的效果,当与用户交互时flag失效
                option= View.SYSTEM_UI_FLAG_FULLSCREEN;
                break;
            case 1:
                //隐藏导航栏,当与用户交互时(如拖动)该flag失效
                option= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
                break;
            case 2:
                //全部隐藏都不透明,当有用户交互,比如点击拖动。flag就会失效
                option= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_FULLSCREEN;
                break;
            case 3:
                //为设置statusbar实现透明铺垫,将statusbar移动到图层的最上面,
                // 当设置statusbar为透明色的时候就可以实现沉浸效果
                // 再调用setStatusBarColor
                // 整个statusbar显示为透明色
                option=View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
                break;
            case 4://半透明效果
                //这个模式也是为实现透明做铺垫,将statusbar,Navigationbar 移动到图层的最上面,
                // 当设置statusbar,NavigationBar设置为透明色的时候就可以实现沉浸效果
                // 再调用setStatusBarColor,setNavigationBarColor,设置为透明色。即可
                option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
                break;

            case 5:
                //隐藏导航栏,有SYSTEM_UI_FLAG_IMMERSIVE,
                // 拖动时隐藏导航栏的flag依然有效。
                // 没有SYSTEM_UI_FLAG_IMMERSIVE,隐藏导航栏的flag立刻失效
                //SYSTEM_UI_FLAG_IMMERSIVE_STICKY和SYSTEM_UI_FLAG_IMMERSIVE效果相同,
                // 只是几秒钟后隐藏导航栏的flag 又会生效
                //这时候如果设置setStatusBarColor颜色为透明色,
                // statusbar只会显示为白色。。因为最下面的底色不透明
                option=View.SYSTEM_UI_FLAG_IMMERSIVE
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
                break;
            case 6:
                //综合应用,当交互时导航栏,statusbar出现。失去焦点时消失
                option=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;

                break;


            default:
                //隐藏statusbar的效果,当与用户交互时flag失效
                option= View.SYSTEM_UI_FLAG_FULLSCREEN;
                break;
        }
        return option;
    }
 /**
   * 19以上实现沉浸式全屏模式
   */
/*
    @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);
        }
    }*/
}

调用view的setSystemUiVisibility(int option) 方法给View设置不同的flag,从而实现不同的布局效果
下面我们一步步分析,不同的flag及flag组合

以上的情况基本涵盖了开发中的大部分情况,很多的flag都具有相互依懒性,所以没有必要去搞清楚每个flag的意思。需要的时候,当做工具类用就可以了。
由于21以下不能设置statusbar和NavigationBar的颜色,不能实现透明化系统栏效果,按着默认颜色显示。但仍然可以实现沉浸全屏模式 ,所以这里做了API版本的判断。 如果你要在API19以上用,只需要修改API版本判断即可(当然那时候状态栏、导航栏按着默认颜色显示)。代码中被我注释掉的部分即是

    //19以上实现沉浸式全屏模式
    @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);
        }
    }

源码由于和另一个Demo写在一起的,所以暂时没上传,后续另一篇文章完成以后会上传的


多谢以下几位大神的无私奉献,如有错误欢迎指正,欢迎转载,但请注明出处,谢谢
沉浸式状态栏引发的血案
Android状态栏微技巧,带你真正理解沉浸式模式-郭神

上一篇下一篇

猜你喜欢

热点阅读