可以看到都有不尽如人意的地方,4.4 系统中内容视图是可以正常延伸到状态栏中,但侧滑菜单中却在上方出现了白条,而在 6.0 中侧滑菜单上会有半透明遮罩。针对 6.0 侧滑菜单半透明遮罩问题,通过设置为 NavigationView 设置属性 app:insetForeground="#00000000" 即可解决。针对 4.4 侧滑菜单白条问题,经过测试,通过对最外层布局设置 setFitsSystemWindows(true) 和 setClipToPadding(false) 可以解决,所以这里对之前的 fitsSystemWindows 方法稍加修改:
/**
* 设置页面最外层布局 FitsSystemWindows 属性
*
* @param activity
*/
private void fitsSystemWindows(Activity activity) {
ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
View parentView = contentFrameLayout.getChildAt(0);
if (parentView != null && Build.VERSION.SDK_INT >= 14) {
//布局预留状态栏高度的 padding
parentView.setFitsSystemWindows(true);
if (parentView instanceof DrawerLayout) {
DrawerLayout drawer = (DrawerLayout) parentView;
//将主页面顶部延伸至status bar;虽默认为false,但经测试,DrawerLayout需显示设置
drawer.setClipToPadding(false);
}
}
}
这样是解决了上述的问题,既然延伸内容没问题了,那就开开心心地像上面一样调用 addStatusViewWithColor() 方法增加个占位状态栏,解决一下内容顶到头的问题吧:
可以看到,效果依然不是我们想要的,虽然占位状态栏是有了,但是却也覆盖到了侧滑菜单上,并且即使设置了 android:fitsSystemWindows="true" 也并没有什么卵用,内容布局依然顶到了头部。这里有两种解决方法:1. 第一种方案是网上提到比较多的,改变 ToolBar 的高度,并增加状态栏高度的 paddingTop,这也是
ImmersionBar 库采用的方案。2. 第二种方案其实思路与第一种差不多,就是将原有的内容布局从 DrawerLayout 中移除,并添加到线性布局(布局中已有占位状态栏),之后再将这个线性布局添加到 DrawerLayout 中成为新的内容布局,此谓狸猫换太子。
/**
* 是否是最外层布局为 DrawerLayout 的侧滑菜单
* @param drawerLayout 是否最外层布局为 DrawerLayout
* @param contentId 内容视图的 id
* @return
*/
public StatusBarUtils setIsDrawerLayout(boolean drawerLayout, int contentId) {
mIsDrawerLayout = drawerLayout;
mContentResourseIdInDrawer = contentId;
return this;
}
/**
* 添加状态栏占位视图
*
* @param activity
*/
private void addStatusViewWithColor(Activity activity, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (isDrawerLayout()) {
//要在内容布局增加状态栏,否则会盖在侧滑菜单上
ViewGroup rootView = (ViewGroup) activity.findViewById(android.R.id.content);
//DrawerLayout 则需要在第一个子视图即内容试图中添加padding
View parentView = rootView.getChildAt(0);
LinearLayout linearLayout = new LinearLayout(activity);
linearLayout.setOrientation(LinearLayout.VERTICAL);
View statusBarView = new View(activity);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
statusBarView.setBackgroundColor(color);
//添加占位状态栏到线性布局中
linearLayout.addView(statusBarView, lp);
//侧滑菜单
DrawerLayout drawer = (DrawerLayout) parentView;
//内容视图
View content = activity.findViewById(mContentResourseIdInDrawer);
//将内容视图从 DrawerLayout 中移除
drawer.removeView(content);
//添加内容视图
linearLayout.addView(content, content.getLayoutParams());
//将带有占位状态栏的新的内容视图设置给 DrawerLayout
drawer.addView(linearLayout, 0);
} else {
//设置 paddingTop
ViewGroup rootView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
rootView.setPadding(0, getStatusBarHeight(mActivity), 0, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//直接设置状态栏颜色
activity.getWindow().setStatusBarColor(color);
} else {
//增加占位状态栏
ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView();
View statusBarView = new View(activity);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
statusBarView.setBackgroundColor(color);
decorView.addView(statusBarView, lp);
}
}
}
}
一番操作后,效果如下:
对于内容视图未使用到 ToolBar 的情况方案二依然可以适用。
ActionBar
上述代码在使用 ActionBar 时可以完美适配吗?测试后效果如下图所示