参考资料
- Android"沉浸式"体验
- SystemUiVisibility flag:Activity 全屏,沉浸式模式这一篇就够了
- 拓展:Android沉浸式状态栏完全解析
涉及的名词
- StatusBar
- NavigationBa
- SystemBar – StatusBar 跟 NavigationBar 的统称
如何设置全屏
参考:http://blog.csdn.net/zhangqinghuazhangzhe/article/details/52935290
4.0 之前采用的方式 (NavigationBar 是在 4.0 以后才引入的。)
4.0 之后新增的方式
4.1 以及之后设置全屏
4.1 以及之后使用 View 的 setSystemUiVisibility()
来对 SystemBar 进行控制。 任何 View 都可以用来调用这个方法,只要它是可见状态的。
下面先把要涉及到的 flag 分组列举出来(所有的 flag 都是以 SYSTEM_UI_FLAG 作为前缀,所以下面将其省略)。
控制 SystemBar 相关:
FULLSCREEN
HIDE_NAVIGATION
LOW_PROFILE
布局相关:
LAYOUT_SCREEN
LAYOUT_HIDE_NAVIGATION
LAYOUT_STABLE
沉浸式相关 (4.4 引入):
IMMERSIVE
IMMERSIVE_STICKY
超前提示:
在离开 App 时,比如按了 home / 多任务键 会导致设置的控制 SystemBar 相关的 flag 被清除,而其他设置的 flag 不会受到影响。
IMMERSIVE
需要配合
View.SYSTEM_UI_FLAG_FULLSCREEN 和 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 一起设置
mDecorView.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);
可以看到设置了该 flag 以后,点击屏幕不会让 SystemBar 显示出来。而在呼出 SystemBar 后,控制 SystemBar 相关的 flag 依然会被清除。
IMMERSIVE_STICKY
跟 IMMERSIVE 不同的是,在该模式下呼出的 SystemBar 会在短暂的显示后自动重新隐藏。在 SystemBar 显示出来的时候点击屏幕中心会立刻让 SystemBar 重新隐藏。所以在模式下不会清除控制 SystemBar 相关的 flag。但是离开 App 时还是会被清除。
所以在回到 App 的时候要重新激活它:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
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);}
}
监听 SystemBar 的变化
参考原文 http://blog.csdn.net/zhangqinghuazhangzhe/article/details/52935290
沉浸式
Android5.x 提出了 Color Palette 的概念,让开发者可以自己设定系统区域的颜色,使整个 App 的颜色风格和系统的颜色风格保持统一。
实现方式
- 在android5.0以上,官方已经提供了透明化系统状态栏的功能支持,就是将colorPrimary与colorParimaryDark设置成一致就行了
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
- 在android4.4上面,实现方式略有不同,它是在透明模式下使用fitsSystemWindows将contentview移至到状态栏的下方,最后在这个空出来的地方手动添加一层view覆盖上去,达到效果.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WindowManager.LayoutParams params = getWindow().getAttributes();
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
//将状态栏设置成全透明
int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
if ((params.flags & bits) == 0) {
params.flags |= bits;
//如果是取消全透明,params.flags &= ~bits;
getWindow().setAttributes(params);
}
//设置contentview为fitsSystemWindows
ViewGroup viewGroup = (ViewGroup) findViewById(android.R.id.content);
viewGroup.getChildAt(0).setFitsSystemWindows(true);
//给statusbar着色
View view = new View(this);
view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(this)));
view.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
viewGroup.addView(view);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//亲儿子里面遇到的问题,不加fitsSystemWindows直接变成全透明样式了
//设置contentview为fitsSystemWindows
ViewGroup viewGroup = (ViewGroup) findViewById(android.R.id.content);
if (viewGroup.getChildAt(0) != null) {
viewGroup.getChildAt(0).setFitsSystemWindows(true);
}
getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimary));
}
}
其中:((ViewGroup)getWindow.getDecorView().findViewById(android.R.id.content)).getChildAt(0),就可以获取 Activity 所设置的 View。