应用市场中越来越多的App都采用了沉浸式状态栏设计(如下图)。状态栏和导航栏颜色相同。Android从4.4开始支持这个效果,但是在4.4下,状态栏只是一个黑框,无法控制。同时4.4和5.0及以上版本对这个效果的支持有所不同。所以要达到这个效果,4.4可以归为一类,5.0及以上可以归为一类。接下来我们将在4.4和5.0及以上版本一步步实现以下效果。导航栏问题在Android中,目前常用的有两种顶部导航栏的实现方式,一种是通过Toolbar,一种是通过自定义View。两种方式各有利弊。Toolbar是官方规范。开发者使用更方便,但扩展性较差,无法实现一些特殊的展示效果。通过自定义方法,可以支持更多的显示效果,但是我们需要写更多的代码。.两种方式在状态栏沉浸的实现上也存在差异。移除标题工具栏的默认主题将有一个标题。当我们在不移除标题的情况下使用Toolbar时,应用程序会崩溃并报如下所示的错误。因此,我们在使用Toolbar时,需要在样式中添加如下属性配置true。当然,我们也可以通过代码动态去除标题,但是当我们的主题继承自Theme.AppCompat作为父类时,就无法通过代码去除标题了。自定义导航栏当我们不设置windowNoTitle属性时,导航栏上方会有一个标题。显然,这与我们想要实现的导航栏的沉浸感是背道而驰的,所以配置true对于实现导航栏的沉浸感是必不可少的。将状态栏设置为透明并去掉标题后,是否可以实现上面的效果呢?这时候我们发现状态栏还是黑色的,没有沉浸。我们需要将状态栏设置为透明。true该属性只能在4.4及4.4以上的版本上配置,不能在低版本上使用。配置该属性后,执行效果如下图所示。解决导航栏上移的问题此时Toolbar被整体上移,导致其部分功能进入到状态栏下方,包括导航栏的内容也进入到状态栏的位置。显然,这不符合我们原来的要求。的。如何解决这个问题呢?我们给Toolbar添加fitSystemWindows属性,可以让toolbar的上半部分有一个高度,让Toolbar的内容和状态栏部分分开。得到我们最终要达到的效果,自定义导航栏与之类似。fitsSystemWindows属性之前对Toolbar的设置是在Toolbar中添加的fitSystemWindows属性,那么当我们将它的属性添加到Toolbar所在的最外层布局时会发生什么呢?后,可以看到同样的效果就像状态栏没有设置透明一样。那么这个fitSystemWindows的工作原理是什么呢?通过以上实验不难发现,这个属性对沉浸式状态栏的控制起着关键作用。接下来通过一个实验来验证这个属性的作用,在Toolbar所在的布局中,在布局底部添加一个Button。当我们给按钮设置这个属性时,会发生什么?通过对比可以明显看出设置View带有fitsSystemWindows属性的设置在其顶部有一个填充。根据前面的实验我们可以知道,当我们将窗口的状态栏设置为透明时,整个contentview都会上移状态栏的高度。当前添加到View的padding的大小是否与其高度相同?Buttonbtn=(Button)findViewById(R.id.test_btn);Log.i("padding",btn.getPaddingTop()+"");Rectframe=newRect();getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);Log.i("高度",frame.top+"");获取按钮的padding高度和状态栏的高度,我们可以得到如下日志。通过实验我们可以得出fitSystemWindows属性会给设置的View增加一个toppadding,所以当我们实现导航栏的沉浸时,设置窗口状态栏的透明度会让view整体上移,并且借助fitSystemWindows属性为视图中的最顶层View设置一个与状态栏等高的padding的功能,这样导航栏就不会被推入状态栏。当我们在一个view的多个View中设置这个属性时,发现只有第一个设置了这个属性的View会起作用。在视图布局中,从上到下的第一个视图将起作用。在层级上,它首先作用于最高层的View。因此,其作用总结如下:给设置该属性的View添加一个与状态栏等高的toppadding。当视图中有多个设置了此属性的视图时,只有布局中最顶层的视图会起作用。5.0及以上,我们完全可以实现状态栏的沉浸感。以上实现是在Android4.4版本上。在视图的顶部,会有一个黑色的渐变阴影,在5.0设备上的显示效果如下,在状态栏上会有一个阴影。当然,不同的厂商有自己的优化。比如魅族就没有4.4的影子。对于5.0及以上版本,官方提供了相应的状态栏颜色控制API。我们可以通过代码控制状态栏的颜色,实现如下效果。实现代码if(Build.VERSION.SDK_INT>=21){Windowwindow=getWindow();//取消设置透明状态栏使ContentView内容不再沉浸在状态栏中window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//需要设置这个flag调用setStatusBarColor设置状态栏颜色window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);//设置状态栏颜色window.setStatusBarColor(getResources().getColor(R.color).yx_red)));}从这里可以看出,我们在实现5.0及以上版本时,可以直接通过代码控制,不需要设置状态栏透明度和fitSystemWindows属性。不过为了适配4.4版本,建议还是按之前的方法来实现,5.0及以上版本想要实现去阴影,可以在代码中手动控制。