需求场景:设置状态栏颜色与设置沉浸式在同一个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显示式修改状态栏字体颜色
参考内容