本文仅仅是将谷歌官方文档做一个翻译+注解,可能会稍微添加一些我自己理解的东西。想看原文的,戳这里 → Managing the System UI
先上一张图
这是一张 google play 的截图,上面用红色圈起来的就是 status bar,下面用绿色圈起来的,就是navigation bar
Android 将 StatusBar 和 NavigationBar 统称为 “SystemBar”。
一般来说,StatusBar 上用来显示一些软件通知、系统信息等。我们可以通过将其亮度调暗或者直接隐藏 StatusBar,以达到“帧·全屏”的效果,譬如播放视频、展示图片,如果显示 StatusBar 的话,会影像观影效果。
NavigationBar 就顾名思义了,提供导航,用于返回等操作。
根据软件的功能,合理的运用 SystemBar,以给用户良好的体验。
在 Android 4.0(API 14)之后,Android 提供了弱化 SystemBar 的方法,也就是说,在 4.0 之前的版本中,如果我们要弱化 SystemBar,需要借助其他方法,这个后面会说道。
将 SystemBar 弱化的好处在于,系统并不会中心调整其 UI 大小,只是相关图标会变化,会变得不再直接显示给用户,如下图:
注意看,弱化之后的 SystemBar 并没有直接隐藏,而是 StatusBar 隐藏了一些图标,只留下了电源和时间(事实上,假如其他 App 也有在 StatusBar 上显示,也会被隐藏),NavigationBar 变成了三个点,当用户触摸 SystemBar 的时候,才会显示出来。
怎么实现这样的效果呢?Android 提供了 SYSTEM_UI_FLAG_LOW_PROFILE
来弱化 StatusBar 和 NavigationBar,使用方法如下:
// This example uses decor view, but you can use any visible view.
View decorView = getActivity().getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE;
decorView.setSystemUiVisibility(uiOptions);
在上面的图片当中我们是通过触摸 SystemBar 来去除弱化效果的,当然也可以通过代码来去除:
decorView.setSystemUiVisibility(0);
API 中对于
SYSTEM_UI_FLAG_LOW_PROFILE
的描述为:设置该 flag,表示该 View 向系统请求进入“低调”模式,该模式用于“读书”、“游戏”、“播放视频”等应用,在该模式下,导航栏以及状态栏图标会变暗,以免用户分心。
有的时候我们需要将 SystemBar 完全隐藏,以达到完全全屏的效果,不同的版本隐藏 SystemBar 的方法也不同。
Android 4.0 (API 14)及更低版本
在这些版本中,可以通过代码或者设置清单文件来隐藏。
<application
...
android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >
...
</application>
if (Build.VERSION.SDK_INT < 16) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
Android 4.1 (API 16)及更高版本
在 4.1 及之后的版本,我们依旧可以通过 setSystemUiVisibility
方法来隐藏,将其设置为 SYSTEM_UI_FLAG_FULLSCREEN
:
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
API 中对于
SYSTEM_UI_FLAG_FULLSCREEN
的描述为:表示该 View 请求进入正常的全屏模式,非关键的屏幕装饰(譬如状态栏)会被隐藏,其内容可以接管屏幕。
需要注意点是,我们设置了隐藏 StatusBar,当我们执行操作唤出 StatusBar 之后,那么该标签就会被清除,如果我们想要重新进入隐藏模式,需要重新设定,我们可以通过设定监听器来监听状态栏的显示状态,会在后面讲到。
有时候我们想要将界面全屏显示,但又想要显示 StatusBar 的内容,那就就用到了所谓的 “沉浸式”,其实也很容易实现,只需要将 StatusBar 设置为透明,然后将我们的布局全屏显示就好:
// 通过 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 将布局设置为全屏显示
View view = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
view.setSystemUiVisibility(option);
// StatusBar 设置为透明
getWindow().setStatusBarColor(Color.TRANSPARENT);
官方文档当中说,最好是将该 flag 和 SYSTEM_UI_FLAG_LAYOUT_STABLE
搭配使用,SYSTEM_UI_FLAG_LAYOUT_STABLE
的作用是帮助应用维持一个稳定的布局(什么意思?没整明白,回头整明白了再补充吧)。
隐藏导航栏和隐藏状态栏一样,都是通过 setSystemUiVisibility
方法设置一个 flag,只不过值换成了 SYSTEM_UI_FLAG_HIDE_NAVIGATION
。
设置了该 flag 之后,NavigationBar 会被隐藏,当点击屏幕时,会再次显示
和沉浸式状态栏一样,同样是两步:1.把布局设置为全屏显示;2.将导航栏设置为透明:
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
getWindow().setNavigationBarColor(Color.TRANSPARENT);
在 Android 4.4(API 19)之后引入了一个新的 flag:SYSTEM_UI_FLAG_IMMERSIVE
,官方文档说它可以让我们的应用进入真正的全屏模式,但是我觉得似乎毫无意义(几乎可以肯定是因为我能力太次认知有限了)。
之前不是说过了隐藏 StatusBar 和 NavigationBar 的方法了么,为什么又要引入这个呢?查询了一系列资料之后得到了解答,往下看。
首先 SYSTEM_UI_FLAG_IMMERSIVE
flag 必须和 SYSTEM_UI_FLAG_HIDE_NAVIGATION
以及 SYSTEM_UI_FLAG_FULLSCREEN
搭配使用,仅仅单独使用该标签是无效的,当它和另外两个 flag 搭配使用的时候,可以达到全屏的效果,当滑动屏幕的时候,另外两个标签会被消除,如果需要回到全屏,需要重新设置。看到这里,这个标签和之前的隐藏状态栏导航栏没啥区别嘛!对,我也这么觉得...哈哈
其实我觉得终点在与 SYSTEM_UI_FLAG_IMMERSIVE
的一个“子类”:SYSTEM_UI_FLAG_IMMERSIVE_STICKY
,使用该该标签和 SYSTEM_UI_FLAG_HIDE_NAVIGATION
以及 SYSTEM_UI_FLAG_FULLSCREEN
搭配使用之后,当我们滑动屏幕唤出状态栏或者导航栏之后,在经过一段时间之后,状态栏又会重新隐藏,无需我们再手动设置隐藏标签。因为这个“显示”只是暂时的,所以在显示的时候并不会出发监听器。
我们可以通过设置监听器来监听 SystemBar 的显示状态,和设置其他基础监听器一样,也没啥好说的 :
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
//do somethings
}
});
需要说明的是一下状态:
导航栏和状态栏都处于隐藏状态:6
导航栏处于隐藏状态:2
状态栏处于隐藏状态:4
状态栏和导航栏处于显示状态:0