注:虽然原生系统从4.4开始,就支持状态栏颜色修改,但因原生6.0以下系统不支持状态栏图标颜色的修改,故此处只讨论6.0以上的处理。
一、修改方案
第一种,设置主题
-
values-23目录下,添加style
<style name="BaseTheme" parent="Theme.AppCompat.Light"> <item name="windowActionBar">false</item> <item name="android:windowActionBar">false</item> <item name="windowNoTitle">true</item> <item name="android:windowNoTitle">true</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/white</item> <item name="android:statusBarColor">@color/white</item> <item name="android:windowLightStatusBar">true</item> <item name="android:navigationBarColor">@color/black</item> <item name="android:windowBackground">@color/white</item> <item name="android:windowAnimationStyle">@style/notAnimation</item> </style>
其中,主要代码:
<item name="android:statusBarColor">@color/white</item>
<item name="android:windowLightStatusBar">true</item> // true:图标为深色;false:图标为浅色
-
清单文件引用
<activity android:name=".activity.MainActivity" android:theme="@style/BaseTheme"/>
-
同样,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<? extends Window> 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