前言
网上沉浸式状态栏的文章一大把,大部分都不能满足需求。所以今天把搜索到的有用的东西总结一下。
沉浸式状态栏
其实就是透明状态栏
搜索到一篇文章里有这样一个思路。
1、通过设置全屏,设置状态栏透明
/**
* 通过设置全屏,设置状态栏透明
*
* @param activity
*/
private void fullScreen(Activity activity) {
//4.4以上才能设置状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.0开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
Window window = activity.getWindow();
View decorView = window.getDecorView();
//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
decorView.setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
//底部导航栏颜色也可以正常设置
// window.setNavigationBarColor(Color.TRANSPARENT);
} else {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams
.FLAG_TRANSLUCENT_NAVIGATION;
attributes.flags |= flagTranslucentStatus;
//底部导航栏
// attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
}
}
}
2、状态栏添加占位视图并自定义颜色
/**
* 添加状态栏占位视图
*
* @param activity
*/
private void addStatusViewWithColor(Activity activity, int colorId) {
//4.4以上才能设置状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//设置 paddingTop 状态栏的高度
ViewGroup rootView = (ViewGroup) activity.getWindow().getDecorView()
.findViewById(android.R.id.content);
rootView.setPadding(0, getStatusBarHeight(activity), 0, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.0以上直接设置状态栏颜色
activity.getWindow().setStatusBarColor(activity.getResources().getColor(colorId));
} else {
//增加占位状态栏
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View statusBarView = new View(activity);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams
.MATCH_PARENT,
getStatusBarHeight(activity));
statusBarView.setBackgroundColor(colorId);
decorView.addView(statusBarView, lp);
}
}
}
在onCreate中调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fullScreen(this);
addStatusViewWithColor(this, R.color.color_ff2600);
}
现在的效果是这样:
通过动态的改变颜色让状态栏占位view的颜色和标题栏一直就可以达到视觉上一体的效果。在没有标题栏的页面上不设置占位view,直接让页面布局顶上去就可以。
修改状态栏文字颜色
目前6.0以上系统,小米、魅族的部分机型支持修改状态栏的文字颜色。只能设置成白色或黑色
我扒了QMUI_Android 的代码。能兼容大部分的机型。
设置状态栏白色字体图标
MIUI:
/**
* 设置状态栏字体图标为深色,需要 MIUIV6 以上
*
* @param window 需要设置的窗口
* @param light 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回 true
*/
@SuppressWarnings("unchecked")
public static boolean MIUISetStatusBarLightMode(Window window, boolean light) {
boolean result = false;
if (window != null) {
Class clazz = window.getClass();
try {
int darkModeFlag;
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 (light) {
extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
} else {
extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
}
result = true;
} catch (Exception ignored) {
}
}
return result;
}
Flyme:
/**
* 设置状态栏图标为深色和魅族特定的文字风格
* 可以用来判断是否为 Flyme 用户
*
* @param window 需要设置的窗口
* @param light 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
public static boolean FlymeSetStatusBarLightMode(Window window, boolean light) {
boolean result = false;
if (window != null) {
// flyme 在 6.2.0.0A 支持了 Android 官方的实现方案,旧的方案失效
Android6SetStatusBarLightMode(window, light);
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 (light) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
result = true;
} catch (Exception ignored) {
}
}
return result;
}
Android 6.0:
/**
* 设置状态栏字体图标为深色,Android 6
*
* @param window 需要设置的窗口
* @param light 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
@TargetApi(23)
private static boolean Android6SetStatusBarLightMode(Window window, boolean light) {
View decorView = window.getDecorView();
int systemUi = light ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : View
.SYSTEM_UI_FLAG_LAYOUT_STABLE;
systemUi = changeStatusBarModeRetainFlag(window, systemUi);
decorView.setSystemUiVisibility(systemUi);
if (DeviceHelper.isMIUIV9()) {
// MIUI 9 低于 6.0 版本依旧只能回退到以前的方案
// https://github.com/QMUI/QMUI_Android/issues/160
MIUISetStatusBarLightMode(window, light);
}
return true;
}
@TargetApi(23)
private static int changeStatusBarModeRetainFlag(Window window, int out) {
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_FULLSCREEN);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
return out;
}
public static int retainSystemUiFlag(Window window, int out, int type) {
int now = window.getDecorView().getSystemUiVisibility();
if ((now & type) == type) {
out |= type;
}
return out;
}
设置状态栏黑色字体图标
/**
* 设置状态栏黑色字体图标,
* 支持 4.4 以上版本 MIUI 和 Flyme,以及 6.0 以上版本的其他 Android
*
* @param activity 需要被处理的 Activity
*/
public static boolean setStatusBarTextBlack(Activity activity) {
if (activity == null) return false;
// 无语系列:ZTK C2016只能时间和电池图标变色。。。。
if (DeviceHelper.isZTKC2016()) {
return false;
}
if (statuBarType != STATUSBAR_TYPE_DEFAULT) {
return setStatusBarLightMode(activity, statuBarType);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (isMIUICustomStatusBarLightModeImpl() && MIUISetStatusBarLightMode(activity
.getWindow(), true)) {
statuBarType = STATUSBAR_TYPE_MIUI;
return true;
} else if (FlymeSetStatusBarLightMode(activity.getWindow(), true)) {
statuBarType = STATUSBAR_TYPE_FLYME;
return true;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Android6SetStatusBarLightMode(activity.getWindow(), true);
statuBarType = STATUSBAR_TYPE_ANDROID6;
return true;
}
}
return false;
}
/**
* 已知系统类型时,设置状态栏黑色字体图标。
* 支持 4.4 以上版本 MIUI 和 Flyme,以及 6.0 以上版本的其他 Android
*
* @param activity 需要被处理的 Activity
* @param type StatusBar 类型,对应不同的系统
*/
private static boolean setStatusBarLightMode(Activity activity, int type) {
if (type == STATUSBAR_TYPE_MIUI) {
return MIUISetStatusBarLightMode(activity.getWindow(), true);
} else if (type == STATUSBAR_TYPE_FLYME) {
return FlymeSetStatusBarLightMode(activity.getWindow(), true);
} else if (type == STATUSBAR_TYPE_ANDROID6) {
return Android6SetStatusBarLightMode(activity.getWindow(), true);
}
return false;
}
/**
* 设置状态栏字体图标为深色,需要 MIUIV6 以上
*
* @param window 需要设置的窗口
* @param light 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回 true
*/
@SuppressWarnings("unchecked")
public static boolean MIUISetStatusBarLightMode(Window window, boolean light) {
boolean result = false;
if (window != null) {
Class clazz = window.getClass();
try {
int darkModeFlag;
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 (light) {
extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
} else {
extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
}
result = true;
} catch (Exception ignored) {
}
}
return result;
}
/**
* 设置状态栏图标为深色和魅族特定的文字风格
* 可以用来判断是否为 Flyme 用户
*
* @param window 需要设置的窗口
* @param light 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
public static boolean FlymeSetStatusBarLightMode(Window window, boolean light) {
boolean result = false;
if (window != null) {
// flyme 在 6.2.0.0A 支持了 Android 官方的实现方案,旧的方案失效
Android6SetStatusBarLightMode(window, light);
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 (light) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
result = true;
} catch (Exception ignored) {
}
}
return result;
}
/**
* 设置状态栏字体图标为深色,Android 6
*
* @param window 需要设置的窗口
* @param light 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
@TargetApi(23)
private static boolean Android6SetStatusBarLightMode(Window window, boolean light) {
View decorView = window.getDecorView();
int systemUi = light ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : View
.SYSTEM_UI_FLAG_LAYOUT_STABLE;
systemUi = changeStatusBarModeRetainFlag(window, systemUi);
decorView.setSystemUiVisibility(systemUi);
if (DeviceHelper.isMIUIV9()) {
// MIUI 9 低于 6.0 版本依旧只能回退到以前的方案
// https://github.com/QMUI/QMUI_Android/issues/160
MIUISetStatusBarLightMode(window, light);
}
return true;
}
最终的效果
相关资料
android4.4以上沉浸式状态栏和导航栏实现以及Bar的其他管理
白底黑字!Android浅色状态栏黑色字体模式
Android实现沉浸式状态栏的那些坑