在android4,4之后可以通过修改状态栏和导航栏实现沉浸式状态栏,在5.0之后增加了其他一些支持。主要通过getWindow().addFlags和getDecorView().setSystemUiVisibility实现相关的设置。
(1)通过getWindow().addFlags设置状态栏
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
通过FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS使根布局可以使用状态栏。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="true"
android:background="@color/colorPrimary"
android:gravity="center_horizontal"
android:textColor="@android:color/white"
android:textSize="20sp"
android:text="测试"
/>
</LinearLayout>
android:fitsSystemWindows="true"的作用使View忽略掉设置的padding,增加一个与状态栏等高的paddingfTop()(只有状态栏透明才有效),这样透明的状态栏会根据头部View的颜色显示自身的颜色,并会一层阴影。但4.4的阴影的效果是渐变,而5.0之后是一层较深的阴影的,为了使两个版本的效果相同。可以在根布局增加一层与状态栏等高的View,并设置其颜色。5.0之后可以单独设置状态栏颜色:getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimary));所以在4.4系统通过添加头部的View设置状态栏颜色,5.0以上通过setStatusBarColor设置状态栏颜色。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_getwindow);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimary));
}else {
addTopView(getResources().getColor(R.color.colorPrimary));
}
}
}
private void addTopView(int color){
ViewGroup contentView = (ViewGroup) findViewById(android.R.id.content);
View view = new View(this);
ViewGroup.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,getStatusBarHeight());
view.setLayoutParams(params);
view.setBackgroundColor(color);
contentView.addView(view);
}
//获取状态栏高度
private int getStatusBarHeight(){
int height = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
//根据资源ID获取响应的尺寸值
height = getResources().getDimensionPixelSize(resourceId);
}
return height;
}
(2)通过getDecorView().setSystemUiVisibility设置状态栏颜色
setSystemUiVisibility中的参数:
View.SYSTEM_UI_FLAG_VISIBLE API 14 默认标记
View.SYSTEM_UI_FLAG_LOW_PROFILE API 14 低调模式, 会隐藏不重要的状态栏图标
View.SYSTEM_UI_FLAG_LAYOUT_STABLE API 16 保持整个View稳定, 常和控制System UI悬浮, 隐藏的Flags共用, 使View不会因为System UI的变化而重新layout
View.SYSTEM_UI_FLAG_FULLSCREEN API 16 状态栏隐藏,效果同设置WindowManager.LayoutParams.FLAG_FULLSCREEN
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN API 16 视图延伸至状态栏区域,状态栏上浮于视图之上
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION API 14 隐藏导航栏
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION API 16 视图延伸至导航栏区域,导航栏上浮于视图之上
View.SYSTEM_UI_FLAG_IMMERSIVE API 19
沉浸模式, 隐藏状态栏和导航栏, 并且在第一次会弹泡提醒, 并且在状态栏区域滑动可以呼出状态栏(这样会系统会清楚之前设置的View.SYSTEM_UI_FLAG_FULLSCREEN或View.SYSTEM_UI_FLAG_HIDE_NAVIGATION标志)。使之生效,需要和View.SYSTEM_UI_FLAG_FULLSCREEN,View.SYSTEM_UI_FLAG_HIDE_NAVIGATION中的一个或两个同时设置。
View.SYSTEM_UI_FLAG_IMMERSIVE_STIKY API 19
与上面唯一的区别是, 呼出隐藏的状态栏后不会清除之前设置的View.SYSTEM_UI_FLAG_FULLSCREEN或View.SYSTEM_UI_FLAG_HIDE_NAVIGATION标志,在一段时间后将再次隐藏系统栏)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setsysui);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN );
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
}
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN的作用使视图衍生至状态栏,状态栏悬浮在视图上,会有一层阴影,所以设置状态栏明。SYSTEM_UI_FLAG_LAYOUT_STABLE
使View不会随UI的变化重新layout,一般与System UI的悬浮和隐藏一起使用。
(3)设置真正的沉浸式状态栏
为什么叫真正的沉浸式状态栏,因为上面的效果只是改变了状态了的颜色,沉浸式状态栏应该像爱奇艺一样播放电影时,隐藏掉状态栏和导航栏,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_immersive);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY );
}
SYSTEM_UI_FLAG_IMMERSIVE 和 SYSTEM_UI_FLAG_IMMERSIVE_STIKY都是设置沉浸式模式,一般与SYSTEM_UI_FLAG_FULLSCREEN或SYSTEM_UI_FLAG_HIDE_NAVIGATION一起使用,当手指在屏幕边缘往内滑时,会显示状态栏和导航栏。但SYSTEM_UI_FLAG_IMMERSIVE显示了状态栏或导航栏后会清楚设置的(SYSTEM_UI_FLAG_FULLSCREEN或SYSTEM_UI_FLAG_HIDE_NAVIGATION),所以就会显示状态栏和导航栏。而SYSTEM_UI_FLAG_IMMERSIVE_STIKY不会清楚掉之前的设置,显示的状态栏或导航栏过几秒会自动隐藏。SYSTEM_UI_FLAG_IMMERSIVE时可以通过getWindow().setStatusBarColor(color)和getWindow().setNavigationBarColor(color)设置状态栏和导航栏的颜色。SYSTEM_UI_FLAG_IMMERSIVE_STIKY时,状态栏和导航栏的颜色默认半透明