简答题
- 全屏、不保留状态栏文字(Splash页面,欢迎页面)
- 全屏保留状态栏文字(页面上部有Banner图)
- 标题栏与状态栏颜色一致(部分App风格)
- 不同Fragment中对StatusBar的处理不一样
- 设置状态栏文字的颜色
- 切换fragment时,toolBar显示与否、statusbar显示与否、statusBar颜色、statusBar文字颜色(新增)
思考题
- Activity中window是怎么回事?里面有什么View/ViewGroup?
- setFitsSystemWindows()是什么鬼?
简答题,是本篇文章阐述的内容;思考题,是针对所阐述的内容做一些拓展,反应两个层面:怎么开发?为什么能实现这样的功能?
演示代码传送门
https://github.com/FokingGit/StatusBarDemo
1
需求一、全屏,不保留状态栏文字(Splash页面,欢迎页面)
这个效果大家脑补下,就不贴图了
首先在style.xml中设置为noActionBar的主题,这是必须的
方式有三种
@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fullscreen_no_text); //方式一 //getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); //方式二 //getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); //方式三 style.xml中配置 //}
2
需求二、全屏保留状态栏文字(页面上部有Banner图)
![08ff4761981a53d5c212953f6f82e9ab.png](https://img-blog.csdnimg.cn/img_convert/08ff4761981a53d5c212953f6f82e9ab.png)
现在项目,大部分向下支持到19,所以先不考虑太低版本的情况
Window window = getWindow();//默认API 最低19 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) { window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); ViewGroup contentView = window.getDecorView().findViewById(Window.ID_ANDROID_CONTENT); contentView.getChildAt(0).setFitsSystemWindows(false);}
3
需求三、标题栏与状态栏颜色一致 xml中配置
![1d545b50a8694de119349a495f40e12b.png](https://img-blog.csdnimg.cn/img_convert/1d545b50a8694de119349a495f40e12b.png)
我们能看到这种处理方式,是可以解决一些业务场景,但是如果在低于21版本手机上就不管用了,那怎么办呢?请接着往下看
Window window = getWindow();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(getResources().getColor(R.color.status_toolBar_same_color));} else { window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); ViewGroup systemContent = findViewById(android.R.id.content); View statusBarView = new View(this); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight()); statusBarView.setBackgroundColor(getResources().getColor(R.color.status_toolBar_same_color)); systemContent.getChildAt(0).setFitsSystemWindows(true); systemContent.addView(statusBarView, 0, lp);}
适配后的结果:
![e679accdfe816fdf2f9d8538ef75a535.png](https://img-blog.csdnimg.cn/img_convert/e679accdfe816fdf2f9d8538ef75a535.png)
4
需求四、不同Fragment中对StatusBar的处理不一样
先上图
![3df7a3e9abef8e3d37001181ebd34d34.gif](https://img-blog.csdnimg.cn/img_convert/3df7a3e9abef8e3d37001181ebd34d34.gif)
上述代码是两个Fragment所依附的Activity对应的部分layout
private void addStatusBar() { //条件状态栏透明,要不然不会起作用 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); if (mStatusBarView == null) { mStatusBarView = new View(FragmentStatusAndActionBarActivity.this); int screenWidth = getResources().getDisplayMetrics().widthPixels; int statusBarHeight = getStatusBarHeight(); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(screenWidth, statusBarHeight); mStatusBarView.setLayoutParams(params); mStatusBarView.requestLayout(); //获取根布局 ViewGroup systemContent = findViewById(android.R.id.content); ViewGroup userContent = (ViewGroup) systemContent.getChildAt(0); userContent.setFitsSystemWindows(false); userContent.addView(mStatusBarView, 0); }}
上面是对应Activity中的布局,意思就是不使用系统提供的ActionBar,使用ToolBar来代替(网上一大推代替的方法),下面的代码中设置,状态栏透明,并且设置了sitFitSystemWindow(false),通过这些操作,我们相当于把系统的StatusBar,ActionBar,都干掉了,那么接下来,我们就可以模拟创建出StatusBaruserContent.addView(mStatusBarView, 0);那么现在我们就可以自己控制statusBar和ActionBar,显示什么颜色?消失还是隐藏?
ToolBar显示的Fragment:
@Overridepublic void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); mActivity.mToolbar.setVisibility(View.VISIBLE);//设置ToolBar显示 //设置statusBar的颜色 mActivity.mStatusBarView.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_bright));}
ToolBar隐藏的Fragment
@Overridepublic void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); mActivity.mToolbar.setVisibility(View.GONE);//设置ToolBar消失 //设置statusBar的颜色 mActivity.mStatusBarView.setBackgroundColor(getResources().getColor(android.R.color.holo_orange_light));}
5
需求五、设置状态栏文字的颜色
![2b5ace37a097933547ec04dbf4abe857.png](https://img-blog.csdnimg.cn/img_convert/2b5ace37a097933547ec04dbf4abe857.png)
//设置白底黑字if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { getWindow().getDecorView() .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);}
但是需要注意的是:目前只有android原生6.0以上支持修改状态栏字体。
除此国内厂商小米、魅族也开放了修改状态栏字体的方式:
- 小米 MIUI6
- https://dev.mi.com/doc/p=4769/index.html
- 魅族 Flyme
- http://open-wiki.flyme.cn/index.php?title=状态栏变色
6
需求六
需求六、切换fragment时,toolBar和statusbar显示与否、statusBar颜色、status文字颜色(新增)
评论区,有同学提出能否"不同Fragment中切换状态栏颜色和状态栏文字的颜色,甚至同时切换风格(纯色状态栏变成banner往上顶的状态栏)的情况",这种情况肯定是没有问题的,也不难,现在状态栏和标题栏都是我们自己,我们想让它怎么样,它不得乖乖听话,对不~
先上图:
![adf3e153afbe0d19516c68e41ddc026a.gif](https://img-blog.csdnimg.cn/img_convert/adf3e153afbe0d19516c68e41ddc026a.gif)
其实调整的不多,这里我只贴下关键代码,gitub代码仓库已更新,大家可以clone看完成代码。
这是只有Banner的fragment:
@Overridepublic void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); //设置ToolBar隐藏 mActivity.mToolbar.setVisibility(View.GONE); //设置statusBar的隐藏 mActivity.mStatusBarView.setVisibility(View.GONE); //恢复默认statusBar文字颜色 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) mActivity.getWindow().getDecorView().setSystemUiVisibility(View.VISIBLE); mActivity.mStatusBarView.setVisibility(View.GONE);}
改变statusBar字体颜色
@Overridepublic void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); //设置ToolBar显示 mActivity.mToolbar.setVisibility(View.VISIBLE); //设置ToolBar的颜色 mActivity.mToolbar.setBackgroundColor(getResources().getColor(R.color.colorAccent)); //设置statusBar的颜色 mActivity.mStatusBarView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); //设置statusBar显示 mActivity.mStatusBarView.setVisibility(View.VISIBLE); //设置statusBar字体颜色 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) mActivity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);}
接下来是思考题。
7
思考一
思考一、Activity中window是怎么回事?里面有什么View/ViewGroup
写了个方法,将整个Window内的View都打印出来了
private void printChildView(ViewGroup viewGroup) { Log.i("printView-ViewGroup