玩转 System Bar ( StatusBar 和 NavigationBar)

1.使 StatusBar 和 NavigationBar 变暗

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);

看下对比图就明白了

玩转 System Bar ( StatusBar 和 NavigationBar)_第1张图片

玩转 System Bar ( StatusBar 和 NavigationBar)_第2张图片

对比图看得很明显 。现在如果我们想它恢复原样呢,有两个方法:
1. 点击 StatusBar 或者 NavigationBar 上的任意地方
2. 用代码清除 flag

View decorView = getActivity().getWindow().getDecorView();
// Calling setSystemUiVisibility() with a value of 0 clears
// all flags.
decorView.setSystemUiVisibility(0);

2.隐藏 StatusBar 和 NavigationBar

2.1隐藏 StatusBar

在 Android 4.0 和 以下的版本隐藏StatusBar

  • 设置Theme
    
  • 设置WindowManager flag
    @Override
    protected void onResume() {
        super.onResume();
//        // hide status bar
        if (Build.VERSION.SDK_INT < 16) {
            // Android 4.0 and lower : set window flag
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        } 
   }

为什么要在 onResume() 中添加代码,而不在 onCreate()中加?
假如我们按 Home 后,再进入就不会执行 onCreate() ,会执行 onResume() ,如果我们还想要我们的效果的话,就在 onResume()中加。 当然我们也可以在 onWindowFocusChanged() 中加。

看下效果图

当鼠标在 StatusBar 地方从上往下滑动时候 , StatusBar 会显示出来,一会就会消失了。

玩转 System Bar ( StatusBar 和 NavigationBar)_第3张图片

Tip: 说是在 Android 4.0 的实现,可以我在5.0 的模拟器上还是可以运行的。

Android 4.1 及以上隐藏 StatusBar

        if (Build.VERSION.SDK_INT < 16) {
            // Android 4.0 and lower : set window flag
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        } else {
            int options = View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    ;
            getWindow().getDecorView().setSystemUiVisibility(options);
            // hide action bar because of no systemUI
            if (getSupportActionBar() != null)
                getSupportActionBar().hide();
        }

看下效果图

玩转 System Bar ( StatusBar 和 NavigationBar)_第4张图片

大家有没有注意到,进行 App 的时候 ,上面会有个空白 ,这是因为 StatusBar 隐藏了,Content 区域要重新计算大小来填充 StatusBar 区域导致的。那么问题来了,如何优化这个? 我们可以让 Content 区域显示在 Status Bar 下面,这样在 StatusBar 隐藏的时候就不用调整大小了。

     @Override
    protected void onResume() {
        super.onResume();
        // hide status bar
        if (Build.VERSION.SDK_INT < 16) {
            // Android 4.0 and lower : set window flag
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        } else {
            int options = View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // make content behind status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE  // keep layout stable
                    ;
            getWindow().getDecorView().setSystemUiVisibility(options);
            // hide action bar because of no systemUI
            if (getSupportActionBar() != null)
                getSupportActionBar().hide();
        }
    }

看下效果

玩转 System Bar ( StatusBar 和 NavigationBar)_第5张图片


2.2. 隐藏 Navigation Bar

隐藏 NavigationBar 是在 Android 4.0 引入的。

            int options = View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // make content behind status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE  // keep layout stable
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide navigation bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // make content behind navigation bar
                    ;

SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 原理同上

效果图

玩转 System Bar ( StatusBar 和 NavigationBar)_第6张图片

现在不需要我们再到 Status Bar 区域往下滑动, 直接点击界面上任意一点,就可以显示 Status Bar 和 Navigation Bar了,是不是方便一点。

Question

一般我们都是同时隐藏 StatusBar 和 NavigationBar 的,并且为了保持布局的稳定性和不被重新计算大小,我们把 Content 区域显示在了 StatusBar 和 NavigationBar 后面, 那么如果我们的 Content 区域是个地图呢? 当 StatusBar 和 NavigationBar 显示后,我们地图岂不是被遮挡了? 所以在面临这样的情况的时候,我们最好不要去隐藏 SystemUI。

3.使用仿真的全屏模式

Immersive Full-Screen Mode:仿真全屏模式(个人翻译)。

SYSTEM_UI_FULLSCREEN | SYSTEM_UI_HIDE_NAVIGATIONBAR 已经是全屏模式,但是呢,我们每次点击屏幕的时候 StatusBar 和 NavigationBar 就会显示出来,在部分时候我们并不需要它们显示,所以在 Android 4.4 ( API 19) 引入仿真全屏模式 SYSTEM_UI_FLAG_IMMERSIVE 。

什么是仿真模式:隐藏 Status Bar 和 Navigation Bar,并让 app 接收屏幕上的所有点击事件。

            int options = View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // make content behind status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE  // keep layout stable
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide navigation bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // make content behind navigation bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE // immersive mode
                    ;

看下效果
玩转 System Bar ( StatusBar 和 NavigationBar)_第7张图片

SYSTEM_UI_FLAG_IMMERSIVE效果: app 接收所有点击事件,如果想要显示,就要在 StatusBar 和 NavigationBar 滑动来显示。不过,一旦显示后,StatusBar 和 NavigationBar 就不会消失了。

还有一种仿真全屏模式,SYSTEM_UI_FLAG_IMMERSIVE_STICKY:app 接收所有点击事件,如果想要显示,就要在 StatusBar 和 NavigationBar 滑动来显示。 不过只显示一会就自动消失了,有点像动画一样。由于它只是一种转变状态,因此不会触发SystemBar( 包括StatusBar 和 NavigationBar )的监听事件,这个后面再说。

            int options = View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // make content behind status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE  // keep layout stable
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide navigation bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // make content behind navigation bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY // immersive sticky mode
                    ;

看下效果

玩转 System Bar ( StatusBar 和 NavigationBar)_第8张图片

这个 StatusBar 和 NavigationBar 是透明的,而且在出现一会就自动消失,这个效果应该就是大部分全屏应用比较喜欢的吧。

4.System Bar的监听事件

在 onCreate() 中添加监听事件。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                    //system bar is visible ,show action bar
                    if (getSupportActionBar() != null) {
                        getSupportActionBar().show();
                    }
                } else {
                    // invisible
                }
            }
        });
    }

上面提到 SYSTEM_UI_FLAG_IMMERSIVE_STICKY 不能触发监听事件,大家可以试试。

你可能感兴趣的:(Android)