关于状态栏沉浸式的处理,很多文章都详细讲到了。我看好多都在沉浸式这个叫法上纠缠不清,结果一张gif就说明了,WTF,这特么不就是全屏外带状态栏和导航栏自动延时隐藏么?索性我就不用这个高大上的词了,免得又把注意力引到这些个概念上(主要是小米没带好头。。。) 4.4以下(不包括4.4)最多做到隐藏状态栏,如果不隐藏,那就接受黑乎乎的一坨吧,变色?你想多了。
总结如下:
设计需求一:
半透明效果,activity内容占全屏(4.4和5.0及以上均保持半透明效果)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
/*因为设置了状态栏半透明,所以activity内容将占据状态栏所在区域,很大可能会使得可视UI元素
*(比如textview所显示的文本或者一个顶部的搜索框)位于状态栏半透明背景下,需要在对应子节点中根据情况
*设置fitsSystemWindows="true",此属性设置在哪个view上,这个view就会将该view的paddingtop值设置为状态栏的高度,
*这时该view的原始paddingtop值将无效
*/
设计需求二:
4.4半透明,5.0及以上全透明(分为两种具体处理方式:1、5.0及以上内容占状态栏区域、2、5.0及以上内容不占状态栏区域)
方式一(占状态栏区域):
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}else if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT){
int flag = getWindow().getDecorView().getSystemUiVisibility();
flag |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
getWindow().getDecorView().setSystemUiVisibility(flag);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
方式二(不占状态栏区域):
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}else if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT){
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
这种情况其实是不存在的,没有哪个设计师会要这种效果。为什么?既要状态栏透明,又不占用状态栏区域,这不就是在activity内容不占用状态栏区域的情况下,将activity的根布局背景颜色显示出来了么(根布局如果没有设置背景色,就会显示所应用主题的背景色)?这种效果给人视觉上的体验就是应用的背景占满了屏幕但是activity的内容UI元素没有铺满整个屏幕,很奇怪
设计需求三:
4.4、5.0及以上给状态栏着色(4.4和5.0以上分开讨论)
4.4上实际是无法给状态栏着色的,但是视觉上可以达到这个效果,那就是先半透明,然后下面的activity内容的颜色就自然而然可以显现出来。照上面"设计需求一"实现半透明后就显示了activity的界面内容颜色(要么纯色要么是非纯色,非纯色是指类似图片的显示)。非纯色显示不用做什么处理,对于纯色,在实现上也可以分为两种:1、类似非纯色的做法,不用作处理,直接显示;2、在顶部添加一个背景是纯色的view,高度等于状态栏高度。
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
View statusBarTintView = new View(this);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, getStatusBarHeight(this));
params.gravity = Gravity.TOP;
statusBarTintView.setLayoutParams(params);
statusBarTintView.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
//这个做法有一点需要注意:添加到顶部的view(冒充状态栏背景)会盖住根布局的上面一条状态栏的区域,因此需要将根布局的paddingtop增加一个状态栏的高度,或者添加fitSystemWindow=true
((ViewGroup)getWindow().getDecorView()).addView(statusBarTintView);
final View container = findViewById(R.id.container);
container.setPadding(container.getPaddingLeft(), container.getPaddingTop() + getStatusBarHeight(this),container.getPaddingRight(), container.getPaddingBottom());
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
}
/*
*获取状态栏高度
*/
public int getStatusBarHeight(Context context) {
Context appContext = context.getApplicationContext();
int result = 0;
int resourceId =
appContext.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = appContext.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
5.0及以上给状态栏着色比较简单,代码如下,这是实实在在地给状态栏着色。也可以像4.4上那样"视觉上"着色。两种方法,方法1跟上述4.4的做法一毛一样,属于半透明的做法;方法2则是全透明的做法,先按上面"设计需求二"全透明化,再按上述4.4的做法(去掉if判断后的第一行)。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimary));
}
附布局代码,主题是Theme.AppCompat.Light.NoActionBar
<?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:orientation="vertical"
android:id="@+id/container"
tools:context="com.example.demo.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="90dp"
android:gravity="center"
android:textSize="25sp"
android:id="@+id/tv"
android:background="@color/colorPrimary"
android:text="Title"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:text="hello world"
android:textSize="20sp"
android:gravity="center"
android:layout_height="match_parent"
android:background="@color/colorAccent"/>
</LinearLayout>
到此4.4以上的关于状态栏沉浸式处理的情况都已囊括到,实际开发中根据需求选择合适的方式就ok了。有遗漏或者不对的,欢迎指正