什么是沉浸式呢?就是状态栏透明,将 activity 布局延伸到整个屏幕,所呈现的一种模式效果。
状态栏透明,深色图标文字是地图 app 常见效果:
关于状态栏的展示效果,官方也是调整多多。在 android4.4 版本之前,用户除了通过全屏模式使之消失外,并不能对状态栏操作什么。而在 android5.0 之前,官方提供了 FLAG_TRANSLUCENT_STATUS 标志位,来控制状态栏是否实现渐变的半透明效果。而到了 android5.0 之后,FLAG_TRANSLUCENT_STATUS 标志位所控制的样式也做了调整,从渐变变成了纯粹的半透明。而到了 android6.0 之后,FLAG_TRANSLUCENT_STATUS 效果再次改变,设置此标志可使状态栏全透明。
Android5.0 以上状态栏透明的代码示例:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// android 5.0+ 状态栏透明
Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
window.getDecorView().setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
}
考虑到状态栏被设置为透明后,状态栏上的文字和图标存在看不清的情况。Android6.0 以上,系统提供了API 来修改状态栏的字体背景色:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
getWindow().getDecorView().setSystemUiVisibility(option);
}
关于沉浸式,难点在于特殊机型的适配工作上。例如小米和魅族手机,在 android4.4 版本之后,FLAG_TRANSLUCENT_STATUS 标志位便显示为全透明效果,而且自 android4.4 之后,其便提供了设置状态栏图标和文字颜色的内部方法。
详情参考开放平台,下载 StatusbarColorUtils 类,接口见下:
/**
* 设置状态栏字体图标颜色
*
* @param activity 当前activity
* @param dark 是否深色 true为深色 false 为白色
*/
public static void setStatusBarDarkIcon(Activity activity, boolean dark) {
setStatusBarDarkIcon(activity, dark, true);
}
详情参考开放平台,对 Android 版本是 6.0 及以后的 OPPO 机型,使用 Google 提供View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 的 Flag 来设置状态栏图标黑色显示效果。
对 Android5.1 版本并且是 ColorOS3.0 的 OPPO 机型使用 ColorOS 提供 SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT 的 Flag 来设置状态栏图标黑色效果,由于该标记未公开,开发者需要在应用代码中定义。
final int SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT = 0x00000010;
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.getDecorView().setSystemUiVisibility(SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT);
为方便开发者对于 OPPO 机型的反色适配,提供了用于设置状态栏显示效果的接口方法,开发者可以根据应用需要动态设置状态栏图标为白色或是黑色。接口传入值 ture 时状态栏图标为黑色,接口转入值为 false 状态栏图标为白色:
public void setLightStatusBarIcon(boolean lightMode) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
int vis = window.getDecorView().getSystemUiVisibility();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (lightMode) {
vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) {
if (lightMode) {
vis |= SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT;
} else {
vis &= ~SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT;
}
}
window.getDecorView().setSystemUiVisibility(vis);
}
详情参考开放平台,在 Android 6.0 以前,Android 没有方法可以实现“状态栏黑色字符”效果,因此 MIUI 自己做了一个接口。在 Android 6.0 及以上版本,Android 提供了标准的方法实现“状态栏黑色字符”效果,但这个方法和 MIUI 的方法产生了冲突。
在新的 MIUI 开发版 7.7.13 及以后版本(基于 Android 6.0 ),设置代码:
Window window = 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);
在旧的 MIUI 版本,仍然需要使用 MIUI 原有的方法,即:
public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
Class<? extends Window> clazz = activity.getWindow().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);
extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
} catch (Exception e) {
e.printStackTrace();
}
}