本文说的沉浸式状态栏不是真正意义上的沉浸式(状态栏会收缩隐藏起来),而是目前国内国产手机提到的沉浸式状态栏,即是状态栏的背景色跟界面顶部(可简单理解为标题栏)的颜色保持一致。

最近发现越来越多的应用开始实现沉浸式状态栏。从视觉角度上看是挺好的。

本文会提及几种实现方式。

方式一:纯色状态栏

先上图吧。

2021 Android沉浸式状态栏 安卓10沉浸式状态栏_android


下面看代码:

public static void initStatusBarStyle(Activity activity, int color) {
        if (Build.VERSION.SDK_INT >= 21) {

            Window window = activity.getWindow();
            //取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

            //需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            //设置状态栏颜色
            window.setStatusBarColor(color);

        }
    }

这里代码量很少,就五六句代码。这种方式其中用到了window.setStatusBarColor(color);故而只能在API21以上系统使用。

同时还存在一种情况,当设置状态栏的颜色为白色的时候,当状态栏的文本颜色也为白色的时候,显示效果就成了这样,

2021 Android沉浸式状态栏 安卓10沉浸式状态栏_标题栏_02


这样就很无语了,没办法,想办法处理咯,最后找到两篇文章,讲了下处理办法,

http://www.jb51.net/article/77804.htm

http://www.zhihu.com/question/31994153

但是也只是提供了小米手机及魅族手机和Android6.0上的处理方法。

我这里测试用的是小米的手机,所以来看下对小米手机的处理方法:

public static boolean setMiuiStatusBarDarkMode(Activity activity, boolean darkmode) {
        Class<? extends Window> clazz = activity.getWindow().getClass();
        try {
            int darkModeFlag = 0;
            Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
            Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
            darkModeFlag = field.getInt(layoutParams);
            Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
            extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

就是通过反射修改相应的系统窗口配置。

下面我们来看下通过以下方式来实现沉浸式状态栏。activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
以上方式是API19之后才有提供的。也就是说使用这种方式只有Android4.4.4及以上方式才能实现沉浸式状态栏。
直接上代码,

public static void initStatusBarStyle(Activity activity, int color) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                activity.getWindow().setStatusBarColor(color);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
                && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
            View statusBarView = contentView.getChildAt(0);
            //避免重复添加statusBarView
            if (statusBarView != null && statusBarView.getMeasuredHeight() == getStatusBarHeight(activity)) {
                statusBarView.setBackgroundColor(color);
                return;
            }
            statusBarView = new View(activity);
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    getStatusBarHeight(activity));
            statusBarView.setBackgroundColor(color);
            contentView.addView(statusBarView, lp);
        }
    }

通过设置activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);后,我们的标题栏会变成半透明效果悬浮在屏幕顶部,而我们的应用界面会全屏显示,我们来看效果:

Android 5.1

2021 Android沉浸式状态栏 安卓10沉浸式状态栏_沉浸式状态栏_03


Android4.4.4

2021 Android沉浸式状态栏 安卓10沉浸式状态栏_状态栏_04


通过图片我们发现存在两个问题,一个是我们的内容跟状态栏重叠了,其二是4.4.4系统的依旧是存在上文说的状态栏颜色(白色)跟文本颜色(白色)的问题。

这里我们来看第一个问题,解决方法是。在我们应用的内容区域(layout中最上面的view)增加android:fitsSystemWindows=”true”属性即可。

或者代码中设置setFitsSystemWindows(true);这个是给状态栏预留空间

我这里顶部是标题栏,就给标题栏设置。设置这个后系统会处理给标题栏增加相应的padding来使得内容区域看上去下移一个状态栏高度的距离。

效果如开文

2021 Android沉浸式状态栏 安卓10沉浸式状态栏_android


下面贴下Android4.4.4中获取状态栏高度的代码

public static int getStatusBarHeight(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

文章中提到的沉浸式存在一定的不足,我再看看怎么优化,有好的建议请留言告诉我。