【Android】6.0|【Android】6.0 状态栏及其图标颜色修改(含MIUI、Flyme适配) 2018-04-19

注:虽然原生系统从4.4开始,就支持状态栏颜色修改,但因原生6.0以下系统不支持状态栏图标颜色的修改,故此处只讨论6.0以上的处理。
一、修改方案
第一种,设置主题

  1. values-23目录下,添加style
    false false true true @color/colorPrimary @color/white @color/white true @color/black @color/white @style/notAnimation

其中,主要代码:
@color/white true // true:图标为深色;false:图标为浅色

  1. 清单文件引用

  2. 【【Android】6.0|【Android】6.0 状态栏及其图标颜色修改(含MIUI、Flyme适配) 2018-04-19】同样,Dialog也可引用
    AlertDialog.Builder alert = new AlertDialog.Builder(activity, R.style.BaseTheme)

第二种,代码动态设置
public void setStatusBarColor(String color, boolean isDark) { try { int colorInt = Color.parseColor(color); setStatusBarColor(colorInt, isDark); } catch (Exception e) {} }public void setStatusBarColor(int color, boolean isDark) { // set statusbar icon color if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// 注:此处实际应区分4.4以上、5.0、6.0以上,进行不同的处理 String osName = "Other"; if (MIUISetStatusBarLightMode(this, isDark)) { osName = "MIUI"; } else if (FlymeSetStatusBarLightMode(this, isDark)) { osName = "Flyme"; } // 以下为原生6.0设置状态栏深/浅色主题的代码。此处因MIUI在Android 6.0 、开发版 7.7.13 及以后版本已舍弃自家的方案,故这里没有分else,而是调用原生方法再次对状态栏图标颜色进行设置。PS:经测试,Flyme没有此问题。 int ui = getWindow().getDecorView().getSystemUiVisibility(); if (isDark) { ui |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } else { ui &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } getWindow().getDecorView().setSystemUiVisibility(ui); getWindow().setStatusBarColor(color); } }/** * MIUI 6.0以上(代码来自MIUI开放平台) * * @param activity * @param isDark * @return */ public static boolean MIUISetStatusBarLightMode(Activity activity, boolean isDark) { return MIUISetStatusBarLightMode(activity.getWindow(), isDark); }public static boolean MIUISetStatusBarLightMode(Window window, boolean isDark) { try { Class clazz = window.getClass(); 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(window, isDark ? darkModeFlag : 0, darkModeFlag); return true; } catch (Exception e) { e.printStackTrace(); } return false; }/** * Flyme 4.0以上 * * @param activity * @param isDark * @return */ public static boolean FlymeSetStatusBarLightMode(Activity activity, boolean isDark) { try { FlymeStatusbarColorUtils.setStatusBarDarkIcon(activity, isDark); return true; } catch (Exception e) { e.printStackTrace(); } return false; }

Flyme设置代码(来自Flyme开放平台)
public class FlymeStatusbarColorUtils { private static Method mSetStatusBarColorIcon; private static Method mSetStatusBarDarkIcon; private static Field mStatusBarColorFiled; private static int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0; static { try { mSetStatusBarColorIcon = Activity.class.getMethod("setStatusBarDarkIcon", int.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { mSetStatusBarDarkIcon = Activity.class.getMethod("setStatusBarDarkIcon", boolean.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { mStatusBarColorFiled = WindowManager.LayoutParams.class.getField("statusBarColor"); } catch (NoSuchFieldException e) { e.printStackTrace(); } try { Field field = View.class.getField("SYSTEM_UI_FLAG_LIGHT_STATUS_BAR"); SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = field.getInt(null); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }/** * 判断颜色是否偏黑色 * * @param color 颜色 * @param level 级别 * @return */ public static boolean isBlackColor(int color, int level) { int grey = toGrey(color); return grey < level; }/** * 颜色转换成灰度值 * * @param rgb 颜色 * @return 灰度值 */ public static int toGrey(int rgb) { int blue = rgb & 0x000000FF; int green = (rgb & 0x0000FF00) >> 8; int red = (rgb & 0x00FF0000) >> 16; return (red * 38 + green * 75 + blue * 15) >> 7; }/** * 设置状态栏字体图标颜色 * * @param activity 当前activity * @param color颜色 */ public static void setStatusBarDarkIcon(Activity activity, int color) { if (mSetStatusBarColorIcon != null) { try { mSetStatusBarColorIcon.invoke(activity, color); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } else { boolean whiteColor = isBlackColor(color, 50); if (mStatusBarColorFiled != null) { setStatusBarDarkIcon(activity, whiteColor, whiteColor); setStatusBarDarkIcon(activity.getWindow(), color); } else { setStatusBarDarkIcon(activity, whiteColor); } } }/** * 设置状态栏字体图标颜色(只限全屏非activity情况) * * @param window 当前窗口 * @param color颜色 */ public static void setStatusBarDarkIcon(Window window, int color) { try { setStatusBarColor(window, color); if (Build.VERSION.SDK_INT > 22) { setStatusBarDarkIcon(window.getDecorView(), true); } } catch (Exception e) { e.printStackTrace(); } }/** * 设置状态栏字体图标颜色 * * @param activity 当前activity * @param dark是否深色 true为深色 false 为白色 */ public static void setStatusBarDarkIcon(Activity activity, boolean dark) { setStatusBarDarkIcon(activity, dark, true); }private static boolean changeMeizuFlag(WindowManager.LayoutParams winParams, String flagName, boolean on) { try { Field f = winParams.getClass().getDeclaredField(flagName); f.setAccessible(true); int bits = f.getInt(winParams); Field f2 = winParams.getClass().getDeclaredField("meizuFlags"); f2.setAccessible(true); int meizuFlags = f2.getInt(winParams); int oldFlags = meizuFlags; if (on) { meizuFlags |= bits; } else { meizuFlags &= ~bits; } if (oldFlags != meizuFlags) { f2.setInt(winParams, meizuFlags); return true; } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (Throwable e) { e.printStackTrace(); } return false; }/** * 设置状态栏颜色 * * @param view * @param dark */ private static void setStatusBarDarkIcon(View view, boolean dark) { int oldVis = view.getSystemUiVisibility(); int newVis = oldVis; if (dark) { newVis |= SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } else { newVis &= ~SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } if (newVis != oldVis) { view.setSystemUiVisibility(newVis); } }/** * 设置状态栏颜色 * * @param window * @param color */ private static void setStatusBarColor(Window window, int color) { WindowManager.LayoutParams winParams = window.getAttributes(); if (mStatusBarColorFiled != null) { try { int oldColor = mStatusBarColorFiled.getInt(winParams); if (oldColor != color) { mStatusBarColorFiled.set(winParams, color); window.setAttributes(winParams); } } catch (IllegalAccessException e) { e.printStackTrace(); } } }/** * 设置状态栏字体图标颜色(只限全屏非activity情况) * * @param window 当前窗口 * @param dark是否深色 true为深色 false 为白色 */ public static void setStatusBarDarkIcon(Window window, boolean dark) { if (Build.VERSION.SDK_INT < 23) { changeMeizuFlag(window.getAttributes(), "MEIZU_FLAG_DARK_STATUS_BAR_ICON", dark); } else { View decorView = window.getDecorView(); if (decorView != null) { setStatusBarDarkIcon(decorView, dark); setStatusBarColor(window, 0); } } }private static void setStatusBarDarkIcon(Activity activity, boolean dark, boolean flag) { if (mSetStatusBarDarkIcon != null) { try { mSetStatusBarDarkIcon.invoke(activity, dark); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } else { if (flag) { setStatusBarDarkIcon(activity.getWindow(), dark); } } }}

二、踩坑 在小米设配上,如果Dialog为全屏显示,状态栏颜色会受Dialog主题影响,而非原来Activity设置的颜色。这时需要在创建Dialog的时候重新设置一下,代码如下:
// set MIUI status bar if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { dialog.getWindow().setStatusBarColor(Color.WHITE); MIUISetStatusBarLightMode(dialog.getWindow(), true); } dialog.show();

参考 http://www.miui.com/thread-8946673-1-1.html
http://open-wiki.flyme.cn/index.php?title=%E7%8A%B6%E6%80%81%E6%A0%8F%E5%8F%98%E8%89%B2

    推荐阅读