Android 4.4之后状态栏和导航栏细节美化(沉浸式状态栏)
文章来源:http://blog.csdn.net/demokui
1. 简介
其实标题我是打算叫“抢眼的沉浸式状态栏”,但是查看多篇文章以及官方文档发现,虽然“沉浸式状态栏”这个名字已经烂大街并且只要一提到这个标签大家都知道是一个什么样的效果,其实沉浸式并不是这样理解的,查看官方文档发现,Google定义的沉浸式模式是4.4带来的新api——ImmersiveMode,进入沉浸式模式的Flag-->SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
进入沉浸式模式之后可以更好的提高用户体验,此时手机屏幕上隐藏了状态栏和导航栏,只显示用户最关心的主体内容,让用户完全沉浸其中,这就是正确的沉浸式,这里我为了提高本文的点击量故意在标题后添加沉浸式标签,哈哈。。。。。
2. 使用场景
正确的沉浸式使用场景其实很少,常用的使用场景如下:
1. 平常app中第一次启动的引导页,还有程序的欢迎界面,这些页面我们平时使用的一般都是全屏模式,设置一个全屏主题就ok了,其实这就是一种沉浸式模式。
2. 游戏ing,现在市面上的Android手游几乎全部是沉浸式模式。
3. 目前很火的视频播放器如爱奇艺、腾讯视频等在播放视频的时候都是沉浸式模式。
这里以腾讯视频播放器为例,相关截图如下:
3. 空间利用(着重记录状态栏)
状态栏是本篇博文的重中之重,Google在android 4.4 之后加入状态栏着色以及空间利用的api,也就是说在4.4之前是没有该功能的,所以我们没必要考虑之前的系统兼容问题,但是4.4和5.0以及5.0+的状态栏着色也是有差别的。那么今天我就以Google出的Material Design设计规范来统一实现4.4以后的系统状态栏着色问题。
1. 空间利用:
1. 相关Flag注释:
1. SYSTEM_UI_FLAG_FULLSCREEN 全屏(隐藏状态栏)
2. SYSTEM_UI_FLAG_HIDE_NAVIGATION 隐藏导航栏(结合全屏Flag使用)
3. SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 主体布局可以利用导航栏空间
4. SYSTEM_UI_FLAG_LAYOUT_STABLE 主体布局可以利用状态栏空间
5. SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 全屏(配合3和4使用)
6. SYSTEM_UI_FLAG_IMMERSIVE_STICKY 真正的沉浸式模式
2. 空间使用:
首先我们定义一个app样式主题同时适配4.4+、5.x、5.x+系统:
1. res/values/styles.xml
<resources>
<style name="BaseAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">#FF4081</item>
</style>
<style name="AppTheme" parent="@style/BaseAppTheme">
</style>
</resources>
2. res/values-v19(如果没有该文件夹请新建)
<resources>
<style name="AppTheme" parent="@style/BaseAppTheme">
这个属性是4.4系统引入的,表示透明化状态栏
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
我起初是在6.0的真机上测试,主题布局可以延伸利用到状态栏空间,但是setStatusBarColor去设置状态栏颜色怎么也设置不上去,最后发现鸿神的文章有
这样一句话如下:
对于5.0由于提供了setStatusBarColor去设置状态栏颜色,但是这个方法不能在主题中设置windowTranslucentStatus属性。
所以要加以下主题设置,本人亲测,问题搞定,
3. res/value-v21
<resources>
<style name="AppTheme" parent="@style/BaseAppTheme">
</style>
</resources>
因为该功能是5.0之后出来的,那么首先判断手机系统版本是否是大于5.0,那么代码如下:
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
如果是4.4到5.0系统的话也还是需要适配的,那么我们可以动态设置一个和状态栏高度和宽度相同的view然后add置主题布局最上面,
把他当成状态栏的背景就好了,或者更简单的直接给我们的主题布局paddingTop一个状态栏的高度就ok了。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
// 获取主体父布局实例
ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
View statusBarView = new View(activity);
// 设置view的宽度为 MATCH_PARENT,高度为状态栏高度
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
// 设置view的颜色(最好和toolBar颜色一致,看起来比较美观也符合Material Design设计规范)
statusBarView.setBackgroundColor(color);
contentView.addView(statusBarView, lp);
}
2. 项目效果展示:
4. 相关Q&A
Q 1. 常见底部四个tab切换Fragment页面,加入第一个和第三个tab将状态栏着色为黑色,第二个和第四个tab将状态栏着色为透明色,这个时候切换页面时第二个和第四个
tab偶尔透明色失效变为黑色,什么情况?
A 1. 首先检查系统版本是否在4.4以上,其次检查以上主题设置和代码逻辑是否编写正确,如果一切都没问题,最后检查tab切换fragment时是用的replace()方法
还是add()和hide() 结合使用,如果是replace()请改为add()方式试试。应该是可以解决此Q。
Q 2. 使用上面的方法只能将主体布局延伸到状态栏的空间上,但无法将状态栏颜色透明化或者上色,如何解决?
A 2. 如果上述方法无法实现,可能是忘了设置API21的主题样式,如果设置还是不行,则请尝试下面这种粗暴的方法,
Window window = getWindow();
// 先清理状态栏和导航栏的状态,然后强制显示状态栏和导航栏并设置flag模式
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
// 重新添加flag
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// 设置状态栏颜色
window.setStatusBarColor(Color.TRANSPARENT);