关于Android沉浸式状态栏变灰的问题

前言

沉浸式状态栏几乎是现在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);
发布了13 篇原创文章 · 获赞 3 · 访问量 9013

猜你喜欢

转载自blog.csdn.net/u012987393/article/details/80024441