android状态栏颜色与沉浸式适配

本文详细介绍了在不同Android版本中,如何设置状态栏颜色和实现沉浸式效果,包括针对小米、魅族及6.0以上版本的API使用方法,以及在不同版本间切换颜色的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求场景:设置状态栏颜色与设置沉浸式在同一个Activity互相切换

设置状态栏颜色


小米或魅族通过私有方法可以自己设置(4.4以上版本)


 /**

     * MIUI的沉浸支持透明白色字体和透明黑色字体

     * https://dev.mi.com/console/doc/detail?pId=1159

     */

    static boolean MIUISetStatusBarLightMode(Activity activity, boolean darkmode) {

        try {

            Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");



            Window window = activity.getWindow();

            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);



            Class<? extends Window> clazz = activity.getWindow().getClass();

            Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");

            int 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;

    }


 /**

     * 设置状态栏图标为深色和魅族特定的文字风格,Flyme4.0以上

     */

    static boolean FlymeSetStatusBarLightMode(Activity activity, boolean darkmode) {

        try {

            WindowManager.LayoutParams lp = activity.getWindow().getAttributes();

            Field darkFlag = WindowManager.LayoutParams.class

                    .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");

            Field meizuFlags = WindowManager.LayoutParams.class

                    .getDeclaredField("meizuFlags");

            darkFlag.setAccessible(true);

            meizuFlags.setAccessible(true);

            int bit = darkFlag.getInt(null);

            int value = meizuFlags.getInt(lp);

            if (darkmode) {

                value |= bit;

            } else {

                value &= ~bit;

            }

            meizuFlags.setInt(lp, value);

            activity.getWindow().setAttributes(lp);

            return true;

        } catch (Exception e) {

//            e.printStackTrace();

        }

        return false;

    }

5.0-6.0之间版本

由于5.0后版本系统开放设置背景颜色的api(window.setStatusBarColor),但是5.0版本未提供更改状态栏颜色的api(6.0后才提供),所以需要针对设置背景色为白色改成默认黑色状态栏显示


  window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

                if (color == Color.WHITE) {//不支持修改字体颜色,采用默认黑色背景

                    color = Color.BLACK;

                }

                //添加Flag把状态栏设为可绘制模式

                window.setStatusBarColor(color);

6.0版本以上(比较完美,没有太大问题)


 window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

                //如果是6.0以上将状态栏文字改为黑色,并设置状态栏颜色

                //会导致默认背景被去除

//                activity.getWindow().setBackgroundDrawableResource(android.R.color.transparent);

                //SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN//影响切换横屏隐藏状态栏

                window.setStatusBarColor(color);



                // 如果亮色,设置状态栏文字为黑色

                if (isLightColor(color)) {

                    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

                } else {

                    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);

                }

通过设置背景颜色修改状态栏字体颜色

需要区分设置背景颜色,偏亮背景设置黑色字体颜色,偏暗背景设置白色字体颜色


private static boolean isLightColor(@ColorInt int color) {

        return ColorUtils.calculateLuminance(color) >= 0.5;

    }

小米魅族根据自己api设置,6.0以上根据下面设置


 // 如果亮色,设置状态栏文字为黑色

                if (isLightColor(color)) {

                    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

                } else {

                    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);

                }

设置状态栏沉浸式(4.4以上支持)


4.4-5.0版本


 static void translucentStatusBar(Activity activity) {

        Window window = activity.getWindow();

        //设置Window为透明

        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);



        removeStatusBar(activity);

    }



    public static void removeStatusBar(Activity activity) {

        ViewGroup mContentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);

        View mContentChild = mContentView.getChildAt(0);



        //移除已经存在假状态栏则,并且取消它的Margin间距

        removeFakeStatusBarViewIfExist(activity);

        removeMarginTopOfContentChild(mContentChild, getStatusBarHeight(activity));

        if (mContentChild != null) {

            //fitsSystemWindow 为 false, 不预留系统栏位置.

            mContentChild.setFitsSystemWindows(false);

        }

    }

5.0以上 支持全透明和半透明


static void translucentStatusBar(Activity activity, boolean hideStatusBarBackground) {

        Window window = activity.getWindow();

        //添加Flag把状态栏设为可绘制模式

        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

        if (hideStatusBarBackground) {

            //如果为全透明模式,取消设置Window半透明的Flag

            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

            //设置状态栏为透明

            window.setStatusBarColor(Color.TRANSPARENT);

            //设置window的状态栏不可见

            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

        } else {

            //如果为半透明模式,添加设置Window半透明的Flag

            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

            //设置系统状态栏处于可见状态

            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);

        }

        //view不根据系统窗口来调整自己的布局

        ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);

        View mChildView = mContentView.getChildAt(0);

        if (mChildView != null) {

            mChildView.setFitsSystemWindows(false);

            ViewCompat.requestApplyInsets(mChildView);

        }

    }

踩坑经验

  • 4.4-5.0版本 沉浸式切换颜色方式后状态栏所占高度无法还原

  • 5.0-6.0版本 可以设置背景颜色,但是设置成白色后状态栏颜色看不清(6.0才提供设置字体颜色api)

  • 6.0版本以上设置成白色背景后dialog如果设置dimAmount完全透明后会导致window背完全透明状态栏字体无法看清,需要在dialog和popwindow显示式修改状态栏字体颜色

参考内容

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值