当前位置: 首页 > 科技观察

Android沉浸式状态栏的入坑之路注意事项

时间:2023-03-13 08:14:55 科技观察

关于“沉浸式状态栏”这个词,可能有小伙伴觉得不妥。但是目前网上所说的“沉浸式状态栏”,基本上都是指“透明状态栏”,这里就不讨论它的对错了(其实有时候太错了,就成了正确的)。大家都知道,说“透明状态栏”就够了,下面就把这种效果称为“沉浸式状态栏”。在Android4.4之前,所有的应用程序都不能设置状态栏的背景色,都沿用了系统(黑色背景状态栏),黑色的状态栏与应用程序不太匹配。为了提供更好的交互效果,谷歌在Android4.4之后提供了设置沉浸式状态栏的方法。支持沉浸式状态栏的app界面更吸引人一点,所以岁数记的Android客户端在年初也支持了沉浸式状态栏。在实现沉浸式状态栏效果的过程中,踩了很多坑,特此记录。下图是Android客户端设置沉浸式状态栏前后的效果对比:对比两种效果,很明显下面的沉浸式状态栏看起来更协调也更美观。2-如何实现沉浸式状态栏2.1-Android4.4以上的实现方法由于Android4.4之后才提供沉浸式状态栏设置,所以我们需要适配Android4.4以上的系统。Android4.4实现沉浸式状态栏有两种方式,一种是在资源文件中设置,一种是在代码中设置。2.1.1-在资源文件中设置沉浸式状态栏首先,我们需要修改values/styles.xml,在里面添加一个空样式,继承自BaseTheme。然后在values-v19目录下的styles.xml文件中添加如下代码(如果项目中没有,新建一个,4.4以上系统会读取该目录下的资源文件):然后设置App的主题到AppTheme即可。注意:属性android:windowTranslucentStatus是在v19中引入的。2.1.2-代码中设置在代码中实现起来更方便,我们只需要在BaseActivity中添加一个FLAGTRANSLUCENTSTATUS的标志即可。通过以上两种方式设置后,效果图如下:我们会发现,只有通过以上设置,Toolbar才会被推入状态栏。通常大家会想到使用fitsSystemWindows属性来解决这个问题。fitSystemWindows官方描述:布尔型内部属性,根据状态栏等系统窗口调整视图布局。如果为真,则调整此视图的填充以为系统窗口留出空间。仅当此视图位于非嵌入式活动中时才会生效。简要说明:该属性的作用是让view根据系统窗口(如状态栏)调整自己的布局。视图添加一个顶部填充,其值是状态栏的高度)。让我们尝试将工具栏的fitsSystemWindows属性设置为true。布局代码如下:上述代码在Android4.4和Android5.0+上的效果对比如下:从上面的对比图可以看出,Android4.4上的状态栏是全透明的,而状态栏在Android5.0+是半透明的。注意:某些4.4系统的状态栏不是全透明的,而是渐变的。2.2-Android5.0以上的实现上面已经实现了沉浸式状态栏的效果,但是如果你在Android5.0以上的机器上运行,你会发现大部分手机的状态栏都是半透明的。也有一些Android5.0以上的App有这种半透明状态栏效果,比如QQ。但有些产品和设计只是想统一风格,全部实现全透明的状态栏。那我们该怎么办呢?从Android5.0开始,为我们提供了设置状态栏颜色的API。我们可以自己设置状态栏的颜色。添加上面的代码,在Android5.0+上运行看看效果。状态栏变成了全透明,和上图Android4.4的效果一样,这里就不画了。2.3-设置状态栏字体颜色Android6.0以上手机默认状态栏字体颜色为白色。如果Toolbar或者界面的header颜色比较浅,状态栏的白字就看不清楚了。Android6.0之后,我们可以通过代码将状态栏字体的颜色设置为黑色。代码如下:3-踩坑。本以为沉浸式状态栏上面已经完美实现了,没想到测试的时候发现了。一连串的坑。3.1-弹出软键盘时向上推工具栏。如果界面中有EditText或者其他输入框,你会发现弹出软件盘的时候,Toolbar的内容被往上推了,如下图:这是为什么呢??经过研究,发现是fitsSystemWindows属性的幽灵。哪个View设置fitsSystemWindows=true,这个View会被软件盘置顶。所以fitsSystemWindows不能乱用,会有意想不到的坑。不能用fitsSystemWindows吗?当然。前面说了fitsSystemWindows=true的作用是给View添加padding也就是状态栏的高度,那么为什么我们不手动给Toolbar添加padding呢?我们去掉Toolbar上的fitsSystemWindows属性,设置Toolbar的padding。代码如下:去掉Toolbar的fitsSystemWindows属性,加入以上代码,弹出软键盘时Toolbar正常。目前Android项目使用代码添加padding来替换fitsSystemWindows属性。3.2-弹出软键盘时,EditText等输入框会被软盘覆盖键盘被覆盖。上面说了添加fitsSystemWindows属性后Toolbar会被软键盘顶住,那么我们是不是可以直接给输入框加一个fitsSystemWindows属性来解决输入框被覆盖的问题呢?果断试试!试了之后发现确实可以,但是输入框的高度变了。其实就是输入框的padding增加了状态栏的高度。显然,这不是一个好的解决方案。后来在stackoverflow上找到解决办法:FLAGTRANSLUCENTSTATUS导致输入框被软键盘覆盖。我们对其进行了一些调整。代码如下:添加上面的类,然后在Activity的onCreate方法中setContentView添加如下代码:然后运行,输入框可以正常上推,不影响输入框的布局。该方案的原理是为界面的根布局设置一个监听器。当界面大小发生变化时,比如弹出键盘时,重新设置根布局的高度,然后调用requestLayout重绘界面。目前Android采用的是这种方案。到目前为止,该方案没有发现其他问题。3.3-华为EMUI3.1上的坑把上面的沉浸式代码放到EMUI3.1系统的手机上(比如华为荣耀7)运行,你会发现完全没有沉浸式效果,状态栏是透明的,并且桌面显示屏幕上的颜色,如下图:经验证,原来是EMUI3.1系统的原因。很多APP在EMUI3.0上也有沉浸效果,但是在EMUI3.1上没有效果。EMUI3.1没有沉浸效果,如果是4.4之前的黑色就好了,所以桌面颜色的透明显示真的很难看。后来发现去掉下面这行代码可以让它有身临其境的效果。效果如下:不过它的状态栏并不是完全透明的,而是像某些4.4系统那样是渐变色的,不过比显示桌面颜色的效果要好。这里我们添加一个判断,判断如果系统不是EMUI3.1,调用clearFlags清除FLAGTRANSLUCENTSTATUS。具体代码如下:3.4-CoordinatorLayout+AppBarLayout滚动隐藏导航栏遇到沉浸式状态栏的坑。这个坑主要是在做财经头条的时候遇到的。需求背景:标题功能需要实现两级TabLayout导航。第一层是Toolbar(标题、产品和发现),第二层是TabLayout,用于在标题中切换各个栏目。实现的效果是在头条Fragment中,滑动帖子列表可以隐藏和显示一级导航Toolbar。一级导航工具栏显示时,左右滑动切换一级导航的标签(即头条、发现、产品)。在头条Fragment中向上滑动帖子列表隐藏一级导航Toolbar后,左右滑动是切换二级导航(即头条各栏)的tab。效果如下图所示。要滚动列表隐藏和显示Toolbar,首先想到的就是CoordinatorLayout+AppBarLayout。基于项目中实现的沉浸式效果,在Activity中添加修改布局:布局是在Toolbar中添加一个TabLayout作为一级导航的tab。然后使用一个ViewPager向ViewPager添加三个Fragment,分别是headlines、products和foundFragments。其中TabLayout和ViewPager嵌套在标题Fragment中。基于沉浸式实现,在代码中为AppBarLayout添加一个状态栏高度的padding。本来以为可以搞定,结果运行后发现,上滑隐藏AppBarLayout再下拉后,会超出下拉范围,即在高度处会多出一个空白下拉时的状态栏,效果如上图:经过不断的尝试和摸索,我发现在Activity中添加如下标志就可以了:嗯,是的,滑动问题已经解决了。可心里总是忐忑不安,总觉得有个坑。后来发现确实有坑。加了这个flag后,部分华为虚拟按键手机出现了虚拟按键遮挡底部布局的问题。经验证,只有EMUI3。最终,几经周折,在CoordinatorLayout+AppBarLayout,为AppBarLayout设置paddingtop后,终于找到了解决滑动问题的有效方法。本以为上面的方案很完美,没有任何问题,没想到还有坑。测试后不久,发现一个现场网络问题:当WebView中的输入框获得焦点,弹出软键盘时,退出界面时底部布局出现软键盘大小的黑色块。如下图所示:经查,此问题是上述代码引起的。没办法,只好把上面的代码去掉,另谋出路处理CoordinatorLayout+AppBarLayout,给AppBarLayout设置paddingtop滑动问题。后来发现在Activity的onCreate方法中加入如下一段代码就可以完美解决这个问题。4-小结以上就是Android项目中沉浸式状态栏实现遇到的坑和解决方法。最后,Android状态栏效果实现后,在不同机型上的效果图如下:沉浸式状态栏开发完成后,需要注意的几个容易踩的坑:1.FitsSystemWindows=true应谨慎使用,有很多陷阱。比如WebView中的输入框获得焦点弹出软键盘时会出现抖动,fitsSystemWindows=true弹出软键盘时会顶到哪个View;2.WindowManager.LayoutParams.FLAGLAYOUTNO_LIMITS请勿使用,会导致EMUI3.1系统下方的虚拟按钮阻塞布局。