前言
沉浸式状态栏几乎是现在Android app的标配,一般我们都是调用setStatusBarTintResource()方法给状态栏设置
一个颜色或透明。但今天在开发中碰见了一个问题,就是Android 7.0环境下,即使给状态栏设成白色,实际显示的颜
色却是灰色,像这样
原因分析
由于这是Android 7.0才会出现的现象,可以断定7.0应该是对状态栏有什么骚操作才会这样,哈哈。那我们顺藤摸瓜
扒一扒源码,看看Android 6.0和7.0有什么不同,你会看到6.0环境下DecorView是PhoneWindow的内部类,
而7.0,DecorView是作为一个单独的类,多了新的属性mSemiTransparentStatusBarColor,找到他的相关代码:
DecorView(Context context, int featureId, PhoneWindow window,WindowManager.LayoutParams params) {
super(context);
......
mForceWindowDrawsStatusBarBackground = context.getResources().getBoolean(
R.bool.config_forceWindowDrawsStatusBarBackground)
&& context.getApplicationInfo().targetSdkVersion >= N;
//设置默认灰色
mSemiTransparentStatusBarColor = context.getResources().getColor(
R.color.system_bar_background_semi_transparent, null /* theme */);
......
}
private int calculateStatusBarColor() {
int flags = mWindow.getAttributes().flags;
return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? mSemiTransparentStatusBarColor
: (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? mWindow.mStatusBarColor : Color.BLACK;
}
calculateStatusBarColor这个方法就是计算得到状态栏的颜色值,其中FLAG_TRANSLUCENT_STATUS是透明标识,如果flags
与FLAG_TRANSLUCENT_STATUS相与不等于0的话就选择默认灰色值mSemiTransparentStatusBarColor。这个
calculateStatusBarColor方法在updateColorViews方法中调用,而updateColorViews方法又onWindowDragResizeStart、
onWindowDragResizeEnd等方法调用,看到这里我们就知道为什么状态栏设置不生效的原因了,这个背景色是动态算出来的。
因此,只要将这个mSemiTransparentStatusBarColor变量值改为透明的就ok了,笑:)
解决思路
通过反射拿到mSemiTransparentStatusBarColor这个属性, 然后实现全透明效果
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
try {
Class decorViewClazz = Class.forName("com.android.internal.policy.DecorView");
Field field = decorViewClazz.getDeclaredField("mSemiTransparentStatusBarColor");
field.setAccessible(true);
field.setInt(getWindow().getDecorView(), Color.TRANSPARENT); //设置透明
} catch (Exception e) {}
}
注意:这段代码需要在setContentView方法前调用。
ok,大功告成,跑起来看
注意的问题
有些人把状态栏设成白色,这会和状态栏字体颜色冲突,导致什么也看不见,
可以使用以下方式将状态栏字体颜色设成黑色就行
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);