美文网首页ITBOXandroid 集结号Android
白底黑字!Android浅色状态栏黑色字体模式

白底黑字!Android浅色状态栏黑色字体模式

作者: 简名 | 来源:发表于2016-05-07 10:55 被阅读54914次

    之前公司项目UI改版的时候,把大部分标题栏都设计成了白色,给我们的设计图是这个样子的:

    设计图.png

    这状态栏布局和图标挺像Android,但是这白底黑字Android设计规范里可没有啊,于是我们开发的时候果断忽视这个状态栏了(当时大部分用户还都是Android 4.4)。

    结果设计师拿着测试版过来问,你们安卓这个状态栏颜色怎么没改啊。

    我:这个做不了。

    设计师一脸质疑。

    我:Android4.4以上系统版本可以修改状态栏颜色,但是只有小米的MIUI、魅族的Flyme和Android6.0以上系统可以把状态栏文字和图标换成深色,其他的系统状态栏文字都是白色的,换成浅色背景的话就看不到了。

    设计师一脸懵逼不知所云。

    后来看着这黑色状态栏白色标题栏实在难看,而且自己用的是MIUI,于是还是做了适配。

    其实很多国内三方Android系统都有深色状态栏字体模式,但是目前只看到了小米和魅族公开了各自的实现方法,小米的支持MIUI V6以上版本,魅族的支持Flyme4.0以上版本。代码如下:

    /**
     * 设置状态栏图标为深色和魅族特定的文字风格,Flyme4.0以上
     * 可以用来判断是否为Flyme用户
     * @param window 需要设置的窗口
     * @param dark 是否把状态栏字体及图标颜色设置为深色
     * @return  boolean 成功执行返回true
     *
     */
    public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.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 (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {
    
            }
        }
        return result;
    }
    
     /**
     * 需要MIUIV6以上
     * @param activity
     * @param dark 是否把状态栏字体及图标颜色设置为深色
     * @return  boolean 成功执行返回true
     *
     */
    public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
        boolean result = false;
        Window window=activity.getWindow();
        if (window != null) {
            Class clazz = window.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);
                if(dark){
                    extraFlagField.invoke(window,darkModeFlag,darkModeFlag);//状态栏透明且黑色字体
                }else{
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                }
                result=true;
    
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
                    if(dark){
                        activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                    }else {
                        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
                    }
                }
            }catch (Exception e){
    
            }
        }
        return result;
    }
    
    MIUI深色状态栏字体模式.png Flyme深色状态栏字体模式.png

    官方在Android6.0中提供了亮色状态栏模式,配置只需一行代码:

      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
       }
    
    6.0原生深色状态栏字体模式.png

    网上有关状态栏颜色设置的文章很多,下面这段代码是我用的状态栏设置工具类,算是一个总结吧。

    官方在4.4版本只提供了状态栏透明的api,大家普遍采用开源库SystemBarTint对4.4版本状态栏颜色进行设置,请各位自行下载。

    在设置状态栏全透明后,整个activity布局都会上移充满整个屏幕,如果你不想让布局上移的话就需要在根布局设置

       android:fitsSystemWindows="true"
    

    以下为我的状态栏设置工具类:

    /**
    * Created by 赵晨璞 
    */
    public class StatusBarUtil {
    
    /**
     * 修改状态栏为全透明
     * @param activity
     */
    @TargetApi(19)
    public static void transparencyBar(Activity activity){
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
         
        } else
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window =activity.getWindow();
            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }
    
    /**
     * 修改状态栏颜色,支持4.4以上版本
     * @param activity
     * @param colorId
     */
    public static void setStatusBarColor(Activity activity,int colorId) {
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
    //      window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);  
            window.setStatusBarColor(activity.getResources().getColor(colorId));
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //使用SystemBarTint库使4.4版本状态栏变色,需要先将状态栏设置为透明
            transparencyBar(activity);
            SystemBarTintManager tintManager = new SystemBarTintManager(activity);
            tintManager.setStatusBarTintEnabled(true);
            tintManager.setStatusBarTintResource(colorId);
        }
    }
    
    /**
     *状态栏亮色模式,设置状态栏黑色文字、图标,
     * 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
     * @param activity
     * @return 1:MIUUI 2:Flyme 3:android6.0
     */
    public static int StatusBarLightMode(Activity activity){
        int result=0;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if(MIUISetStatusBarLightMode(activity, true)){
                result=1;
            }else if(FlymeSetStatusBarLightMode(activity.getWindow(), true)){
                result=2;
            }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                result=3;
            }
        }
        return result;
    }
    
    /**
     * 已知系统类型时,设置状态栏黑色文字、图标。
     * 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
     * @param activity
     * @param type 1:MIUUI 2:Flyme 3:android6.0
     */
    public static void StatusBarLightMode(Activity activity,int type){
        if(type==1){
           MIUISetStatusBarLightMode(activity, true);
        }else if(type==2){
            FlymeSetStatusBarLightMode(activity.getWindow(), true);
        }else if(type==3){
            activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }
    
    }
    
    /**
     * 状态栏暗色模式,清除MIUI、flyme或6.0以上版本状态栏黑色文字、图标
     */
    public static void StatusBarDarkMode(Activity activity,int type){
        if(type==1){
            MIUISetStatusBarLightMode(activity, false);
        }else if(type==2){
            FlymeSetStatusBarLightMode(activity.getWindow(), false);
        }else if(type==3){
            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
        }
    
    }
    
    
    /**
     * 设置状态栏图标为深色和魅族特定的文字风格
     * 可以用来判断是否为Flyme用户
     * @param window 需要设置的窗口
     * @param dark 是否把状态栏文字及图标颜色设置为深色
     * @return  boolean 成功执行返回true
     *
     */
    public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.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 (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {
    
            }
        }
        return result;
    }
    
     /**
     * 需要MIUIV6以上
     * @param activity
     * @param dark 是否把状态栏文字及图标颜色设置为深色
     * @return  boolean 成功执行返回true
     *
     */
    public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
        boolean result = false;
        Window window=activity.getWindow();
        if (window != null) {
            Class clazz = window.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);
                if(dark){
                    extraFlagField.invoke(window,darkModeFlag,darkModeFlag);//状态栏透明且黑色字体
                }else{
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                }
                result=true;
    
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
                    if(dark){
                        activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                    }else {
                        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
                    }
                }
            }catch (Exception e){
    
            }
        }
        return result;
    }
    }
    

    适配浅色状态栏深色字体的时候发现底层版本为Android6.0.1的MIUI7.1系统不支持View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR设置,还是得用MIUI自己的深色字体方法。

    2017年7月,小米才终于想起来对状态栏字符颜色的逻辑做了一次调整,改为兼容Android原生的设置方式,但是没给出怎么区分旧系统与新系统的方法==、
    关于 MIUI 状态栏字符颜色逻辑调整的说明
    没办法,只能在设置MIUI状态栏的地方把两种方法都写上。

    三方Android系统对底层改的挺乱的,也是让人头痛。O__O


    神马?写了这么多,你就说了句图里的妹子挺好看的。。。

    图片是随手从网上找的。。。

    如果你觉得本文有点用处或是觉得我找的这张图不错就请随手点个赞吧。。。

    相关文章

      网友评论

      • 吃饱了就送:第520个点赞
      • AxeChen:很实用啊,谢谢大佬!
      • 七岁就狠拽:Nubia 6.0的机子使用View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR失效
      • 嗜武狂魂:我知道,她叫程熙媛,好多人都叫她程序猿,谐音有点像
      • 刘晨光_3bce:写得好,很有用
      • very_mrq:卧槽,好喜欢这个妹子
      • 猪上村树:谢谢楼主。
      • 你的益达233:魅族的没效果,你们就没测出来???
        BertSir:魅族的还是用官方提供的Utuils没问题 http://open-wiki.flyme.cn/index.php?title=%E7%8A%B6%E6%80%81%E6%A0%8F%E5%8F%98%E8%89%B2
      • largecatfish:楼主 图片妹子很好看
      • aef9b848dcba:哈哈哈,我还真说了句这姑娘真好看,点赞点赞
      • 51f82b05f43f:项目里还是没法用啊,ov、菊花手机该怎么适配呢?
      • 坐不住的程序员:5.0的设置状态栏白色背景的话,要设置透明度
      • 坐不住的程序员:5.0不起作用,setStatusBarColor设置白色后,全是白色了
      • 160a7ecaa2a0:说了一堆没说怎么用?
      • 就这样很好:是不是不能适配所有手机品牌
      • Luh的星河:写的不错 领教了
      • StillForward:备用,谢谢楼主
      • SQcoder:贴吧和有一些应该他们怎么可以在6.0以下手机做到文字白底黑字的呀
      • DrunkPian0:为什么instagram在魅族上也是白底黑字?instagram都被墙了,难道也对魅族做适配了吗
        花香_Android:魅族有个自带的沉浸式状态栏,在设置里面,开了的话会自动给你app加沉浸式
        Blazer:哈哈哈哈
      • 阿V很简单:赞是给妹子的啊
        shawn168:妹子真的太好看了!!!!
      • 浪够_:bz好啊,最近在做这个,在oppo手机上遇到了问题,没有找到如何修改coloros系统的状态栏字体颜色,bz知道吗
      • kotonoha:7.0原生锁屏正常解锁,进入指定应用,设置浅色背景深色字体有效,
        通过锁屏界面相机进入相机,然后退出,进入指定应用,设置浅色背景深色字体就无效
      • 扈扈哈嘿:能不用美女的图片吗:joy:
      • MOMOsShare:ZUK6.0+没效果咋办
      • d730f99d117f:为什么我设置android:fitsSystemWindows="true"后,在ToolBar那个位置出现一个白色区域
      • fb544bab5a2b:复制图片地址,百度图片,以图搜图,发现美的眼睛👀
      • 罗小黑写写文字:妹子叫 程熙媛
      • 小剑哥:你好,写的很好,转载了代码并首行表明出处,如介意请回复我删除.
      • 0a2780cac9d9:改了颜色后,如何将文字颜色恢复成原来系统颜色
      • 翼展哈哈:其实我比较好奇,UI问你的时候你是怎么知道只有MIUI和魅族的手机是公开了那些API的?BTW,谢谢楼主的文章。
        简名:@翼展哈哈 因为到用户较多的几个厂家的开发者平台看了圈 就小米和魅族文档里有写状态栏的api...
      • qq1109345:你好,代码试了几天了。有个问题就是,6.0的方案下,调黑色字体,一定要设成FULLSCREEN才有效,这会导致有些页面的导航栏跟状态栏重叠在一起。问下,有没有什么解决方案? :blush:
        ac90cd96f51b:http://www.jianshu.com/p/34a8b40b9308 这里有介绍
        ac90cd96f51b:加个padding值就好.
      • 94462ca61516:作为一个设计师,虽然我看不懂。但是为了图片 我还是特地注册一个账号来评论你
      • 日离我远点:图片灰常不错 :blush:
      • 逆水行舟丶:这里面都是历史遗留的坑
      • 相互交流:LZ问个问题,白底黑字!Android浅色状态栏黑色字体模式 如果不是这个需求,,需求是其他的颜色的,,类似于QQ,,是不是都能实现????
      • nihaoya:6.0之前的Android其他手机是改不了的么?
      • 被帅熨斗掰直的迷妹:请问要怎么用在项目中呢?小白,不造怎么用ORZ
      • 189af35c2d2b:“这状态栏布局和图标挺像Android” 23333333333
        卤煮对你们公司的设计师怨念很深啊。。
      • 侬脑子瓦塌了:我在使用的时候if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 这一句的LOLLIPOP会报错,是否因为sdk版本低还是别的原因?
        简名:@侬脑子瓦塌了 sdk版本低的过
      • 灰灰鸽:有些第三方不仅不开放自己的API,连Android6.0的方案都不兼容。。丧心病狂啊
        七岁就狠拽:例如Nubia, 例如Nubia, 例如Nubia
      • Jooyer:我一定要打赏你,写得非常好,我用了也非常好!
      • 爱下雪的孩子:写的真好。 :pray: 膜拜
      • totato:别说国内小米魅族坑,事实是谷歌官方的实现也是巨坑

        查api后发现:For this to take effect, the window must request FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS but not FLAG_TRANSLUCENT_STATUS.

        也就是说 谷歌官方的白底黑字跟透明状态栏是冲突的,也就是状态栏如果想用白底黑字,那状态栏下面就不可能有图片
        imknown:用透明状态栏 + 白色background 的 layout xml 试试
      • f2631bd59014:6.0.1 的小米 ;单纯用 6.0方法无效 、用小米特定修改方法有效 ;亲测 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        9801c8f568b2:什么特定方法,求分享
        thsai:@葉胖胖灬 同
      • zouzhenglu:小米跟6.0可用,,魅族测试了两台都不行
        606fd5f5448c:怎么判断是不是google的6.0呢
        zouzhenglu:@简名 5.0的,刚去官网看了下,发现是要设置了他的沉浸式后才能生效
        简名:@a77d196a13f7 http://open-wiki.flyme.cn/index.php?title=Flyme%E7%B3%BB%E7%BB%9FAPI这个是Flyme开放平台文档地址。魅族api是基于Flyme4.0以上系统,我在MX4 Pro和魅蓝metal上测试可以实现,你的Flyme系统版本是多少?
      • fuuuuuccccck:谢谢~ 已经用到自己的项目中
      • FindCrt:好图:smile:
      • gavinL:这个必须赞\(≧▽≦)/
        简名:@gavinL =^_^=
      • 嘿张开心:谢谢分享
        简名:@z_Coder 大家一起讨论,共同进步
      • 28ae3d1b9194:其他手机就没法适配了吧!
        简名:@安卓辉 很多厂商没有公开api,而且有些市场份额不大。现在6.0系统越来越多了
      • 一杯茶一本书:不错
        简名:@一杯茶一本书 谢谢
      • 扣子兮兮:图片很美
        简名:@fix扣子 :smile:
      • 2da3fa0e022e:受益良多 多来点Android的
        简名:@晓晓寻风 后续会分享更多,大家一起讨论进步
      • 收稿君:可否分享背景照片给我,给你点赞
        收稿君: @简名 👍
        简名:@朱哥哥 http://huaban.com/pins/349586999/
      • drf:看在图的份上,跟我审美观相近,点个赞
        简名:@drf 谢谢哈~

      本文标题:白底黑字!Android浅色状态栏黑色字体模式

      本文链接:https://www.haomeiwen.com/subject/rinjrttx.html