写这篇文实在是因为网上流传了太多鱼龙混杂的文章,各种东拼西凑,而且只讲方法不讲道理。所以我尽量做到,最后给出的解决方案是能看得懂的。
这里不讨论“沉浸式”“沉浸式状态栏”“透明状态栏”的定义,能知道我这篇讲的是“透明状态栏”,说明这些概念你已经搞清楚了。
真正意义上的(全)透明状态栏,只有Android 5.0及以上才支持
关于
windowTranslucentStatus
该style属性以及windowTranslucentNavigation,是在Android 4.4中被引入的。
参考
在Android 4.4上,如果为主题启用了这两个属性,状态栏和导航栏部分会变为由黑色开始的透明渐变;在Android 5.0以上,启用了这两个属性,状态栏和导航栏会变为纯粹的半透明:
注意事项:
1.启用透明状态栏,布局将填充系统状态栏后面的区域,所以必须为不应被系统状态栏覆盖的布局部分启用
fitsSystemWindows。
2.设置windowTranslucentStatus,会自动为window添加
View.SYSTEM_UI_FLAG_LAYOUT_STABLE和
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN这两个flag。
关于
statusBarColor
该Window的方法在Android 5.0中被引入。
官方对该API的介绍:
Sets the color of the status bar to color. For this to take effect, the window must be drawing the system bar backgrounds with
FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS and
FLAG_TRANSLUCENT_STATUS
must not be set.
If color is not opaque, consider setting
SYSTEM_UI_FLAG_LAYOUT_STABLE
and
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
.
The transitionName for the view background will be "android:status:background".
主要是几点:
1.该方法可以设置状态栏的颜色。为了使该方法生效,FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS要启用,FLAG_TRANSLUCENT_STATUS要禁用,即保持这两个flag的默认值。
2.如果颜色值不是不透明的(实际上就是有透明度,但不一定完全透明),要设置SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN。
经过测试:
设置两个flag 不设置两个flag color透明 状态栏透明,且布局填充到状态栏区域 状态栏不透明(color叠加到纯白色背景上),布局正常 color不透明 状态栏不透明,布局填充到状态栏区域 状态栏不透明,布局正常 由测试结果可以看出,这两个flag的作用主要是将布局拉到状态栏的区域,同时透明化状态栏。单纯设置color的颜色,状态栏仍然占据原来的位置,所以不透明。
3.默认情况下,android:statusBarColor 将继承 android:colorPrimaryDark 的值。
透明状态栏的具体实现
综上,可以得到设置透明状态栏的方法(仅Android 5.0以上)。
1.设置状态栏为透明色
/res/values-v21/styles.xml
<item name="android:statusBarColor">@android:color/transparent</item>
或者在代码中(因为只有Android 5.0以上才有setStatusBarColor方法,所以调用之前一定要检查系统版本)if (Build.VERSION.SDK_INT >= 21) { View decorView = getWindow().getDecorView(); getWindow().setStatusBarColor(Color.TRANSPARENT); }
2.设置相应的window flag
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
结合1当中,纯代码实现:if (Build.VERSION.SDK_INT >= 21) { View decorView = getWindow().getDecorView(); int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; decorView.setSystemUiVisibility(option); getWindow().setStatusBarColor(Color.TRANSPARENT); }
3.在需要的地方,设置android:fitsSystemWindows="true",让系统根据状态栏的高度设置一个合适的padding。
其他
有两种情况:
1.MIUI等在Android 4.4上自己实现的透明状态栏,在设置windowTranslucentStatus之后,呈现的不是渐变透明,而是全透明。
2.当UI布局的标题栏背景为纯色,Android 5.0以上依然可以使用上面的方法设置状态栏为透明。但是更简单的方法是,直接设置状态栏的颜色为标题栏的颜色,视觉效果一样。
3.对于导航栏,与之对应的有navigationBarColor属性,setNavigationBarColor方法,且有类似的使用规则:
Sets the color of the navigation bar to . For this to take effect, the window must be drawing the system bar backgrounds with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS and FLAG_TRANSLUCENT_NAVIGATION must not be set. If is not opaque, consider setting SYSTEM_UI_FLAG_LAYOUT_STABLE and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION.The transitionName for the view background will be "android:navigation:background".
参考
https://stackoverflow.com/a/28041425/4083396
https://developer.android.com/training/material/theme.html#StatusBar
https://developer.android.com/about/versions/android-4.4.html#UI
https://www.zhihu.com/question/31468556/answer/52169988
http://www.jianshu.com/p/28f1954812b3
http://blog.csdn.net/guolin_blog/article/details/51763825