Android系统栏包括状态栏(status bar)和导航栏(navigation bar)。
开发者可以对系统进行操作,具体包括:
- 弱化系统栏(Dimming the System Bars)
- 隐藏状态栏(Hiding the Status Bar)
- 隐藏导航栏(Hiding the Navigation Bar)
- 使用沉浸式全屏模式(Using Immersive Full-Screen Mode)
- 响应系统栏的改变(Responding to UI Visibility Changes)
- 状态栏上色
- 导航栏上色
弱化系统栏
原文参见
什么是弱化系统栏?简而言之就是弱化系统栏对用户的视觉冲击,可以使用户将更多注意力转移到App提供的内容。
要求:弱化系统栏操作,只有Android 4.0或更高版本的设备支持。
效果:
- 状态栏消失(仍占位);导航栏图标变为小圆点
- 不会改变
serContentView()
方法中参数布局的大小 - 用户操作会使系统栏重新可见
实现:
// This example uses decor view, but you can use any visible view.
View decorView = getActivity().getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE;
decorView.setSystemUiVisibility(uiOptions);
取消弱化系统栏:
View decorView = getActivity().getWindow().getDecorView();
// Calling setSystemUiVisibility() with a value of 0 clears
// all flags.
decorView.setSystemUiVisibility(0);
隐藏状态栏
原文参见
什么是隐藏状态栏?简而言之就是使状态栏区域的内容消失(占位隐藏);或让状态栏的整个区域都不可见(完全隐藏)。
分类:
- 占位隐藏
- 完全隐藏
占位隐藏实现:
这里介绍的实现方法基于Android 4.1及更高的版本。低版本的隐藏参见原文...
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;//隐藏状态栏
visibleView.setSystemUiVisibility(uiOptions);
完全隐藏实现:
这里介绍的实现方法基于Android 4.1及更高的版本。低版本的隐藏参见原文...
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN//隐藏状态栏
|View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;//无论状态栏隐藏与否,让布局在状态栏区域显示
visibleView.setSystemUiVisibility(uiOptions);
隐藏导航栏
原文参见
要求:隐藏导航栏操作在Android4.0版本引进。
分类:
- 占位隐藏
- 完全隐藏
占位隐藏实现:
int uiOptions = View. SYSTEM_UI_FLAG_HIDE_NAVIGATION;//隐藏导航栏
visibleView.setSystemUiVisibility(uiOptions);
完全隐藏实现:
int uiOptions = View. SYSTEM_UI_FLAG_HIDE_NAVIGATION//隐藏导航栏
|View. SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;//无论导航栏隐藏与否,让布局在导航栏区域显示
visibleView.setSystemUiVisibility(uiOptions);
使用沉浸式全屏模式
原文参见
响应系统栏的改变
原文参见
状态栏上色
参考1
参考2
对于状态栏:
- 隐藏
- 显示
对于状态栏的隐藏,上文已经介绍。这里介绍状态栏按照需求进行显示的问题。那么,状态栏的显示有哪些需求呢?我分析如下:
- 指定状态栏背景颜色
- 指定状态栏元素颜色
对于第二个问题,待以后研究,这里只分析如何指定状态栏背景(色)。
API21及以上
设置状态栏背景色的实现可以调用如下方法:
public abstract class Window {
/**
For this to take effect,the window must be drawing the system bar backgrounds with
android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS and
android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS must not be set
**/
public abstract void setStatusColor(int color);
}
注意:
- 该方法在Android 5.0(API 21)
- 引入通过注释可知,要使方法生效,需要其他的操作配合:
- window不能设置
android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
标签 - window必须设置
WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
标签
- window不能设置
API20及以下
低版本的系统是不支持给状态栏着色的,但却可以通过透明状态栏+透明背景颜色来实现相同的效果。
- 将系统状态栏设置为透明
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
- 设置
Activity
根布局的背景颜色为预期状态栏背景色
注意:当设置了状态栏为透明后,Activity
会相当于一个FullScreen的全屏设置,窗口会占满整个屏幕,整体的内容会往上移动一段状态栏高度的距离,这样就会导致状态栏覆盖到我们的内容。这时,我们需要在根布局上设置android:fitsSystemWindows="true"
,这样系统会帮我们重新调整窗口的位置避免出现覆盖的情况(无非就是给我们的窗口加上一个padding
值)
沉浸式状态栏
public static void immersingStatusBar(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.0以上
Window window = activity.getWindow();
//清除导航栏和状态栏的半透明属性
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//设置系统的ui
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//将窗口的状态栏设置成透明的
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
沉浸式导航栏
- 调用如下方法
关键代码
public void immersingNvigationBar(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0以上
Window window = activity.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION//布局在导航栏区域有值
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);//布局稳定
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setNavigationBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4版本到5.0以下
Window window = activity.getWindow();
//将系统栏设置成透明的
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
- 设置关键元素的margin(包含顶部元素和底部元素)
是否有导航栏
public boolean checkDeviceHasNavigationBar(Context context) {
boolean hasNavigationBar = false;
Resources rs = context.getResources();
int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
if (id > 0) {
hasNavigationBar = rs.getBoolean(id);
}
try {
Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
Method m = systemPropertiesClass.getMethod("get", String.class);
String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
if ("1".equals(navBarOverride)) {
hasNavigationBar = false;
} else if ("0".equals(navBarOverride)) {
hasNavigationBar = true;
}
} catch (Exception e) {
}
return hasNavigationBar;
}
获取导航栏高度
private int getNavigationBarHeight() {
Resources resources = getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
int height = resources.getDimensionPixelSize(resourceId);
Log.v("dbw", "Navi height:" + height);
return height;
}
设置底部元素margin
//设置底部,也可以通过fitsSystemWindows属性实现,但对该属性暂不熟悉,因此使用下面方法保证底部元素不与导航栏重叠
if(checkDeviceHasNavigationBar(this)){
FrameLayout.LayoutParams param = (FrameLayout.LayoutParams) llBottom.getLayoutParams();
param.bottomMargin = getNavigationBarHeight();
llBottom.setLayoutParams(param);
}
设置顶部元素margin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
FrameLayout.LayoutParams param = (FrameLayout.LayoutParams) llBack.getLayoutParams();
param.topMargin = getStateBarHeight();
llBack.setLayoutParams(param);
}
沉浸式系统栏
public void immersingSystemBar(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0以上
Window window = activity.getWindow();
//清除导航栏和状态栏的半透明属性
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
//设置系统的ui
window.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION//布局在导航栏区域有值
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN//布局在状态栏有值
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);//布局稳定
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
window.setNavigationBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4版本到5.0以下
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
备注:
- 青葱西点模块首页采用沉浸式系统栏
- 青葱西点商品详情界面采用沉浸式状态栏
- 罗曼蒂克首页采用沉浸式状态栏