Android状态栏和导航栏的使用

1,029 阅读3分钟

系统栏

系统栏包括顶部的状态栏和底部的导航栏

将状态栏调暗

View decorView = getActivity().getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE;
decorView.setSystemUiVisibility(uiOptions);

这种调节方式可逆,只要对状态栏有任务的触摸,都会让它回到原来的样子;我们也可以使用代码的方式手动还原,如下代码:

View decorView = getActivity().getWindow().getDecorView();
decorView.setSystemUiVisibility(0);

顶部状态栏

在android4.1以上使用 setSystemUiVisibility() 方法控制状态栏

如下代码代码隐藏状态栏:

View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
//一般不显示状态栏也不会显示操作栏
ActionBar actionBar = getActionBar();
if (actionBar != null)
    actionBar.hide();

使用这种方法隐藏状态栏时只要界面失去焦点就会失效,想要再次隐藏就得再次调用;上述方式隐藏的状态栏的变化会影响到下面我们设计的界面,要想使我们设计的界面的大小不随其变化(将内容延伸到状态栏),可以使用以下flag:

        View decorView = getWindow().getDecorView();
        int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(uiOptions);
        //一般不显示状态栏也不是显示操作栏
        ActionBar actionBar = getActionBar();
        if (actionBar != null)
            actionBar.hide();

使用这种方式同样只要界面失去焦点就会失效,想要再次隐藏就得再次调用;还会引发的一个问题就是当我们把内容延伸到了状态栏之后,状态栏显示出来时,我们的内容会被遮挡掉,而此时状态栏也不会再隐藏了,解决这个问题可以在我们的 xml 文件的根目录设置属性

android:fitsSystemWindows="true"

底部导航栏

隐藏导航栏,这种方式隐藏的导航栏只要点击屏幕任意位置,都是使隐藏失效

View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
decorView.setSystemUiVisibility(uiOptions);

使内容延伸到导航栏:

        View decorView = getWindow().getDecorView();
        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(uiOptions);

全屏模式

1.向后倾斜模式。使用以下模式只要点击屏幕任意位置就会失效:

View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
decorView.setSystemUiVisibility(uiOptions);

2.沉浸模式。必须屏幕两端滑动才会使全屏失效:

View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
decorView.setSystemUiVisibility(uiOptions);

3.粘性沉浸模式。沉浸模式的升级版,从屏幕两端滑动使全屏失效,但是如果此时不对系统栏做其他的触摸事件的话,又会自动变成全屏模式,唯一的缺点是无法监听系统栏的显示与否(下面讲监听系统栏的显示与否)

View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
decorView.setSystemUiVisibility(uiOptions);

监听页面的可见性

  1. onWindowFocusChanged 方法,只要设计区被遮住或者重新显示都会触发此回调:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    //hasFocus 是否可见
}

2.监听系统栏的状态(粘性沉浸模式无法收到此回调):

View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener
        (new View.OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                    //此时系统栏是显示的
                    
                } else {
                    //此时系统栏是隐藏的
                    
                }
            }
        });

通过上文我们知道粘性沉浸模式可以让系统栏显示后自动隐藏,但是我们收不到显示和隐藏的回调,所以我们无法在系统栏的状态变化时响应其他操作。比如:我既想要自动隐藏状态栏又想监听其状态的变化,此时可以使用 向后倾斜模式 + 监听器 + Handler 完成:

private final Handler mHandler = new Handler();
public void setListener(View view) {
    View decorView = getWindow().getDecorView();
    decorView.setOnSystemUiVisibilityChangeListener
            (new View.OnSystemUiVisibilityChangeListener() {
                @Override
                public void onSystemUiVisibilityChange(int visibility) {
                    if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                        //此时系统栏是显示的
                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                //3秒后隐藏系统栏
                                View decorView = getWindow().getDecorView();
                                int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
                                decorView.setSystemUiVisibility(uiOptions);
                            }
                        },3000);
                    } else {
                        //此时系统栏是隐藏的
                    }
                }
            });
}