什么是沉浸式,实际上,官方的沉浸式指的是全屏模式,不过,现在在国内,沉浸式状态栏普遍的被认为是类似于ios系统那样,透明的状态栏。
目前情况是Android 4.4(API 19,包括API 19)以上才能实现沉浸式状态栏,Android 5.0(API 21 包括21)以上能设置状态栏背景颜色,Android 6.0(API 23包括API 23)以上能够设置状态栏文字和图标的颜色,小米、魅族手机从Android 4.4以上就支持修改背景颜色和状态栏图标文字颜色。但是小米手机在开发版7.7.13以前版本为了达到能够修改状态栏文字和图标颜色的效果,自定义了接口,在开发版7.7.13以后自定义接口作废,使用Android原生的方法实现,为了能够在新老版本上都有效果,需要将两种方法同时写出来。
下面就给出一些实现方法:
一、Android 4.4~Android5.0(不包括5.0)
其实这种方法在Android4.4以上版本中都适用,只不过有缺陷,这种方法在某些手机上有半透明的阴影,在5.0以后版本中有更好的解决办法:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
效果图:
![](https://i-blog.csdnimg.cn/blog_migrate/ce8e8bfa102b51169ec19f5bff37ca2a.png)
android 5.0华为荣耀手机
![](https://i-blog.csdnimg.cn/blog_migrate/6c80fc8babb5ed37a220bc8638c421bf.png)
Android5.0模拟器
可以看到确实有半透明的阴影,有的是渐变的,有的是纯色半透明,我们还可以发现,我们的布局的内容显示在了状态栏的下面,这不是我们想要的,以下几种方法来解决这个问题:
a、给根布局设置标记
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rootView"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.rootView).setFitsSystemWindows(true);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
![](https://i-blog.csdnimg.cn/blog_migrate/a6d42b0077eafba523fd9ed8c4a9cc11.png)
android 5.0华为荣耀手机
![](https://i-blog.csdnimg.cn/blog_migrate/a66dcad6ef9b13b2864670bfaf29b1e0.png)
Android5.0模拟器
这种方式可以将状态栏颜色与根布局颜色保持一致,这也是4.4到5.0(不包括5.0)系统的一种改变状态栏颜色的一种方式,但是这种方式有些问题,目前遇到的是如果在一个activity中切换多个fragment时,只会在第一个fragment上产生效果,其余的fragment不会有效果
b、给根布局设置paddingTop
我们还可以通过给根布局添加与状态栏相同高度的paddingtop的方式来达到上面的效果,状态栏的颜色会与根布局保持一致,如果想让内容布局不使用与根布局相同的颜色,那么可以单独设置,这可能会导致过度渲染,不过这种方法比较简便
获取状态栏高度的方法:
public int getStatusBarHeight()
{
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
{
return getMainActivity().getResources().getDimensionPixelSize(resourceId);
}
return -1;
}
c、在根布局的上面添加一个与状态栏相同高度的占位View
这种方式其实与b方法大同小异,不做过多解释
二、Android5.0以上版本
在Android5.0以上版本有更好的解决办法来规避第一种方法中的半透明阴影问题,可以直接调用api设置状态栏背景颜色:
if(Build.VERSION.SDK_INT>=21){
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
设置状态栏文字颜色
在Android6.0以前没有办法设置状态栏文字颜色,6.0之后才有设置文字颜色的api:
//设置Android6.0以上以及MIUI系统自7.7.13 开发版以后的沉浸式状态栏文字颜色
private void setCommonStatusBarDarkMode(boolean darkmode)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)//6.0以上版本直接用原生api
{
//设置内容布局在状态栏的后面
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
//设置状态栏文字图标颜色
mWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
option = option | (darkmode ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : View.SYSTEM_UI_FLAG_VISIBLE);
//由于windowTranslucentStatus会与6.0以上设置沉浸式状态栏冲突,取消掉
mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
mWindow.getDecorView().setSystemUiVisibility(option);
//设置状态栏的背景颜色
mWindow.setStatusBarColor(Color.TRANSPARENT);
}
}
特殊情况:
魅族手机设置状态栏文字颜色,需要使用魅族独有的api,无论哪个安卓版本,使用原生api无效
//设置魅族沉浸式状态栏文字颜色
private void setMeiZuStatusBarDarkMode(boolean darkmode)
{
LogUtil.d(TAG, "setMiuiStatusBarDarkMode_Flyme:" + darkmode);
try
{
WindowManager.LayoutParams lp = mWindow.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);
mWindow.setAttributes(lp);
}
catch (Exception e)
{
}
}
小米手机为了兼容老版本和新版本,需要同时使用自定义API和原生API
//设置小米沉浸式状态栏文字颜色
private void setMIUIStatusBarDarkMode(boolean darkmode)
{
LogUtil.d(TAG, "setMiuiStatusBarDarkMode_miui:" + darkmode);
Class<? extends Window> clazz = mWindow.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(mWindow, darkmode ? darkModeFlag : 0, darkModeFlag);
}
catch (Exception e)
{
e.printStackTrace();
}
//为了兼容低版本和高版本小米系统,需要两种方式都写
setCommonStatusBarDarkMode(darkmode);
}