Android 沉浸式状态栏的实现 (3)

可以看到都有不尽如人意的地方,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() 方法增加个占位状态栏,解决一下内容顶到头的问题吧:

4.4 系统,增加占位状态栏异常

可以看到,效果依然不是我们想要的,虽然占位状态栏是有了,但是却也覆盖到了侧滑菜单上,并且即使设置了 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); } } } }

一番操作后,效果如下:

改进 addStatusViewWithColor() 后的效果

对于内容视图未使用到 ToolBar 的情况方案二依然可以适用。

ActionBar

上述代码在使用 ActionBar 时可以完美适配吗?测试后效果如下图所示

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgyysw.html