沉浸式
沉浸式是一种完全的全面屏体验,是指状态栏和导航栏被隐藏的全面屏展示。
android 4.0 以下
在4.0以下可以通过WindowManager.LayoutParams.FLAG_FULLSCREEN
来隐藏状态栏,一般来说隐藏状态栏也需要隐藏ActionBar,所以代码实现如下:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.hide();
}
效果图
通过WindowManager.LayoutParams.FLAG_FULLSCREEN
实现了状态栏的隐藏。
android 4.1 及以上
在android4.1及以上,安卓在view级别提供了setSystemUiVisibility()
来控制UI的样式。设置的flag会对应到window级别上,因此提供了更精细的控制。
View.SYSTEM_UI_FLAG_FULLSCREEN 隐藏状态栏
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 布局占用状态栏区域
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 隐藏导航栏
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 布局占用导航栏区域
View.SYSTEM_UI_FLAG_LAYOUT_STABLE 稳定布局
View.SYSTEM_UI_FLAG_IMMERSIVE 沉浸式
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 粘性沉浸式
为了达到沉浸式并且布局可以占用到状态栏和导航栏,我们需要设置上 面前五条flag。
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
);
效果图
效果看起来不错,不过任何的触控操作都会导致flags被清除,导航栏和状态又会出现了且不会消失,这可能与我们的需求不太一致。
View.SYSTEM_UI_FLAG_IMMERSIVE:
View.SYSTEM_UI_FLAG_IMMERSIVE
代表沉浸式,View.SYSTEM_UI_FLAG_IMMERSIVE
只有与结合 SYSTEM_UI_FLAG_FULLSCREEN 和SYSTEM_UI_FLAG_HIDE_NAVIGATION结合时才有作用。此标志设置后,只有当用户用手指从屏幕上方向下滑动或者屏幕下方向上滑动时才会导致flags被清除,导航栏和状态又会出现了并且不会消失。
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|View.SYSTEM_UI_FLAG_IMMERSIVE
需要注意的是一旦UI flags被清除了,你的app需要重新设置这些flags。你可以在在 onResume() 或者 onWindowFocusChanged()方法中重新设置UI flags。
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
如果你想效果和上面说的一样,但过几秒后可以自动恢复到沉浸式,你可以用View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
来替代View.SYSTEM_UI_FLAG_IMMERSIVE
,sticky在用户从屏幕上方下滑或者屏幕下方上话时不会真正的清除flag,状态栏和导航栏会在显示短暂几秒后重新消失。View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
同样只有与结合 SYSTEM_UI_FLAG_FULLSCREEN 和SYSTEM_UI_FLAG_HIDE_NAVIGATION结合时才有作用。
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
);
导航栏与状态栏透明
有的时候产品要求的并不是沉浸式,而是导航栏与状态栏透明或者与页面中整体颜色一致。
这种效果并没有隐藏状态栏与导航栏,而是将状态栏与导航栏与页面整体色调一致。
android 5.0 及以上
在Android 5.0以上,系统提供了API来设置状态栏和导航栏的颜色,非常方便。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setBackgroundDrawable(new ColorDrawable(0xFFFF4081));
}
getWindow().setStatusBarColor(0xFFFF4081);
getWindow().setNavigationBarColor(0xFFFF4081);
}
如果你的activity是继承子AppCompatActivity,选择NoActionBar相关的主题。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(0xFFFF4081);
getWindow().setNavigationBarColor(0xFFFF4081);
}
android 4.4 到android 5.0
Android4.4到5.0没有方式直接来设置状态栏和标题栏颜色,只能通过技术手段达到类似效果。
方案一:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
这种方案实现的透明并不是真正的透明,效果也受厂商定制影响。
从效果上看这是一种半透明方案,而且我们的内容也顶到状态栏去了。为了让系统预留空间正确显示,我们还要在相应布局上加如下配置:
android:fitsSystemWindows="true"
加了这个属性的view系统会自动添加padding来预留显示内容,并且只有第一个设置的生效。比如你在根布局添加 android:fitsSystemWindows="true"
,根布局就会相当于上面加状态栏高度的paddingTop,下面添加导航栏高度的paddingBottom。
方案二:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
获取状态栏和导航栏的高度,修改顶部和底部布局参数。
//获取状态栏高度 px
public int getStatusBarHeight() {
int result = 0;
int resourceId = Resources.getSystem().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = Resources.getSystem().getDimensionPixelSize(resourceId);
}
return result;
}
//获取导航栏高度px
public int getNavigationBarHeight() {
int result = 0;
int resourceId = Resources.getSystem().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = Resources.getSystem().getDimensionPixelSize(resourceId);
}
return result;
}
修改自定义的toolbar padding。
int statusHeight=getStatusHeight();
toolbar.setPadding(toolbar.getPaddingLeft(), toolbar.getPaddingTop() + statusHeight, toolbar.getPaddingRight(), toolbar.getPaddingBottom());
//判断是否有导航栏
private boolean haveNavigation() {
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
//拿到真实屏幕分辨率
display.getRealMetrics(displayMetrics);
int heightDisplay = displayMetrics.heightPixels;
//为了防止横屏状态
int widthDisplay = displayMetrics.widthPixels;
DisplayMetrics contentDisplaymetrics = new DisplayMetrics();
//获取应用真正显示大小
display.getMetrics(contentDisplaymetrics);
int contentDisplay = contentDisplaymetrics.heightPixels;
int contentDisplayWidth = contentDisplaymetrics.widthPixels;
//屏幕内容高度 显示内容的屏幕
int w = widthDisplay - contentDisplayWidth;
int h = heightDisplay - contentDisplay;
return w > 0 || h > 0;
}
if (haveNavigation()) {
int navigationBarHeight=getNavigationBarHeight();
bottomView.setPadding(bottomView.getPaddingLeft(), bottomView.getPaddingTop(), bottomView.getPaddingRight(), bottomView.getPaddingBottom() +navigationBarHeight);
bottomView.setBackgroundColor(color);
}