一、刘海屏适配
简述
随着互联网的飞速发展,Android系统经过10余年的更新迭代,Google每年都会发布新的版本,在用户体验、流畅性、续航、安全、隐私等方面不断改进,同时还会新增一些特性。2018年发布了Android 9.0系统,增加了刘海屏设备的支持。
在之前的很长一段时间里,绝大多数的手机屏幕使用的都是16:9的比例。当时普遍认为16:9就是最合适的设备屏幕比例,因为手机上方还要给听筒摄像头留足空间,下方还要给Home键留足空间。在2016年的时候,小米推出了MIX一代手机,将屏幕做到了接近18:9的比例,并首次提出了全面屏的概念。但是要做到真正的全面屏并不是一件容易的事情,像Home键之类的实体按键还可以用虚拟按键来替代,但是前置摄像头这种就是实打实的硬件传感器了,必须得要占据一定的空间。因此,小米MIX选择了将摄像头做到了屏幕下方,形成了一个比较宽的下巴。
从那个时候开始,绝大多数的手机厂商都开始想要突破16:9的屏幕比例限制了,其中也包括苹果。2017年,苹果推出了iPhone产品的10周年纪念手机——iPhone X,库克声称,它将会引导未来10年的手机发展方向。iPhone X最主要的变化就是其首次在iPhone设备上应用了全面屏的概念,将屏幕做到了19.5:9的比例,取消了使用10年之久的Home按键,改为使用FaceId来进行身份认证。而FaceId是需要通过摄像头进行面部识别来认证身份的,因此苹果同样无法绕过的一个问题就是,前置摄像头应该放在哪里?和小米MIX的做法不同,iPhone X采用了将屏幕切出一个凹口的方式来放置前置摄像头以及其他传感器硬件,因此形成了一种非标准矩形屏幕。由于切出的凹口很像人的刘海,因此被很多人称为刘海屏。
iPhone X推出之后,一大堆的国产手机厂商也立即跟风去生产刘海屏的Android手机。当时的Android 8.0系统还不支持刘海屏设备。每个手机厂商为了不落后于他人,都通过修改ROM的方式制订了一套自己的API标准,有的是在AndroidManifest里面配置属性的,有的是通过反射来进行赋值的,有的是读取system feature的,总之什么方式的都有。没有一个统一的标准,2018年Google推出的Android 9.0系统对刘海屏进行了支持,我们只需要按照Android官方提供的标准API来进行刘海屏设备的适配即可。
iPhone手机刘海的位置和大小基本上是固定的,而Android手机的刘海不同的厂商定制的位置和大小是不一样的。常见的有下面这些:
准备工作
我们在适配的时候,不可能找到所有样式的刘海手机来测试,其实只需要一个Android 9.0系统或以上的手机或者模拟器就行了,在开发者选项中设置一下Display cutout选项就可以模拟各种刘海屏幕了。
对于刘海屏的适配目标就是不要让刘海部分遮挡应用程序或者影响到应用程序的正常操作,Android 9.0系统中提供了3种layoutInDisplayCutoutMode属性来允许应用自主决定该如何对刘海屏设备进行适配。
1、LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
这是一种默认的属性,在不进行明确指定的情况下,系统会自动使用这种属性。这种属性允许应用程序的内容在竖屏模式下自动延伸到刘海区域,而在横屏模式下则不会延伸到刘海区域。
2、LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
这种属性表示,不管手机处于横屏还是竖屏模式,都会允许应用程序的内容延伸到刘海区域。
3、LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
这种属性表示,永远不允许应用程序的内容延伸到刘海区域。
可以通过在主题xml或者在代码中动态指定用哪一种适配方案。
开始适配
如果选择在主题xml文件中进行指定,需要先创建一个values-v28文件夹,并在其中创建一个styles.xml文件,然后在指定Activity的主题下加入如下配置即可:
<style name="ActivityTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowLayoutInDisplayCutoutMode">
shortEdges <!-- 可选项 default, shortEdges, never -->
</item>
</style>
如果选择在代码中进行指定,只需要在Activity中加入如下代码即可:
if (Build.VERSION.SDK_INT >= 28) {
WindowManager.LayoutParams params = getWindow().getAttributes();
params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
getWindow().setAttributes(params);
}