Android 沉浸式状态栏
- 当我听说沉浸式状态栏的时候我的大脑是空白的。脑袋里想的是 “什么意思”。于是我百度了一下,下面是我总结的一些方法:
- 第一种是设置主题Theme。
- 因为 API21 之后(也就是 android 5.0 之后)的状态栏,会默认覆盖一层半透明遮罩。且为了保持4.4以前系统正常使用,故需要三份 style 文件,即默认的values(不设置状态栏透明)、values-v19、values-v21(解决半透明遮罩问题),代码如下:
<!-- values-v21 -->
<style name="MyTranslucentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<!--//设置是否全屏-->
<!--<item name="android:windowFullscreen">false</item>-->
<!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<!-- values-v19。v19 开始有 android:windowTranslucentStatus 这个属性-->
<style name="MyTranslucentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<!--//设置是否全屏-->
<!--<item name="android:windowFullscreen">false</item>-->
</style>
<!-- values-->
<style name="MyTranslucentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
- 在没有去掉ActionBar时候Android5.0上运行的效果如下,主要想看下状态栏是什么样子,它主要是浅灰色。
- 由上图可以看出,其实布局中的内容已经占用了状态栏,布局中有一个Textview
内容是HelloWord文字,为了效果明显我们去掉其中的ActionBar,并且给Textview设置高度和背景颜色。如下图
很明显,这个TextView延伸到了状态栏,可能在有个情况需要状态这块地方(其实这种情况不存在的),下面我介绍几种解决办法:
方法一设置fitsSystemWindows属性
当该属性设置 true 时,会在屏幕最上方预留出状态栏高度的 padding。在布局的最外层设置 android:fitsSystemWindows=”true” 属性。当然,也可以通过代码设置:
/**
* 设置页面最外层布局 FitsSystemWindows 属性
* @param activity
* @param value
*/
public static void setFitsSystemWindows(Activity activity, boolean value) {
ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
View parentView = contentFrameLayout.getChildAt(0);
if (parentView != null && Build.VERSION.SDK_INT >= 14) {
parentView.setFitsSystemWindows(value);
}
}
- 效果图如下:
通过该设置保留状态栏高度的 paddingTop 后,再设置状态栏的颜色。就可以达到设想的效果。但这种方式实现有些问题,例如我们想设置状态栏为蓝色,再也不能通过在styles.xml配置 如下属性来设置颜色了。
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
只能通过设置最外层布局的背景为蓝色来实现,然而一旦设置后,整个布局就都变成了蓝色,只能在下方的布局内容里另外再设置白色背景,而这样就存在过度绘制了。而且设置了 fitsSystemWindows=true 属性的页面,在点击 EditText 调出 软键盘时,整个视图都会被顶上去。如下:
方法二 代码添加占位状态栏
核心代码如下
手动给根视图设置一个 paddingTop ,高度为状态栏高度,相当于手动实现了 fitsSystemWindows=true 的效果,然后再在根视图加入一个占位视图,其高度也设置为状态栏高度。
效果如下:(左边是虚拟机右边是真机)
下图是android6.0的虚拟机效果图,它的导航栏变成了灰色。5.0以上导航栏没有显示成透明。5.0以下起作用。
方案二 全屏模式
通过设置 FLAG ,让应用内容占用系统状态栏的空间.
/**
* 通过设置全屏,设置状态栏透明
*
* @param activity
*/
private void fullScreen(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
Window window = activity.getWindow();
View decorView = window.getDecorView();
//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
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);
}
}
}