关于刘海屏的适配方案有两种:
- 可以在刘海屏区域展示,即使部分内容被『吃掉』也没关系;
- 不可以在刘海屏区域展示,避免重要的信息不能被用户看到,影响使用。
本文针对这两种情况进行分析:
知识储备
window.decorView.systemUiVisibility 的可选值(部分)
View.SYSTEM_UI_FLAG_VISIBLE
默认标记。显示状态栏和导航栏,Activity 正常显示。
View.INVISIBLE
隐藏状态栏,同时Activity会伸展全屏显示。
View.SYSTEM_UI_FLAG_LOW_PROFILE
低调模式, 会隐藏不重要的状态栏图标
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
保持整个View稳定, 常和控制System UI悬浮, 隐藏的Flags共用, 使View不会因为System UI的变化而重新layout
View.SYSTEM_UI_FLAG_FULLSCREEN
状态栏隐藏,Activity全屏显示。效果同设置WindowManager.LayoutParams.FLAG_FULLSCREEN
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
视图延伸至状态栏区域,状态栏上浮于视图之上
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
隐藏导航栏
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
视图延伸至导航栏区域,导航栏上浮于视图之上
View.SYSTEM_UI_FLAG_IMMERSIVE
沉浸模式, 隐藏状态栏和导航栏, 并且在第一次会弹泡提醒, 并且在状态栏区域滑动可以呼出状态栏(这样会清除之前设置的View.SYSTEM_UI_FLAG_FULLSCREEN 或 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION标志)。使之生效,需要和 View.SYSTEM_UI_FLAG_FULLSCREEN,View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 中的一个或两个同时设置。
View.SYSTEM_UI_FLAG_IMMERSIVE_STIKY
与上面唯一的区别是, 呼出隐藏的状态栏后不会清除之前设置的View.SYSTEM_UI_FLAG_FULLSCREEN或View.SYSTEM_UI_FLAG_HIDE_NAVIGATION标志,在一段时间后将再次隐藏系统栏)。
layoutInDisplayCutoutMode(Android P 提供)
模式 | 模式说明 |
---|---|
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT | 只有当DisplayCutout完全包含在系统栏中时,才允许窗口延伸到DisplayCutout区域。 否则,窗口布局不与DisplayCutout区域重叠。 |
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER | 该窗口决不允许与DisplayCutout区域重叠。 |
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES | 该窗口始终允许延伸到屏幕短边上的DisplayCutout区域。 |
在刘海屏区域内展示内容,部分内容被『吃掉』不影响
效果如下:
这种方案比较好适配,如果是 Android 9.0 及以上系统,使用官方提供的方案,否则设置布局延伸到状态栏即可。
1 | package com.xiaomai.demo |
内容重要,不能在刘海屏区域展示
思路:首先检查设备是否是刘海屏,如果是的话则设置不在状态栏显示内容,如果不是话则可以在状态栏显示。
检测设备是否是刘海屏的思路:
1 | class FullActivity : AppCompatActivity() { |
以下是通过反射获取 Android P 版本以下的设备是否是刘海屏的代码:
1 | object DisplayCutoutUtils { |
带虚拟导航的 Pad 设备
有的 Pad 在横屏时,虚拟导航在屏幕右侧,而有的在屏幕下方。有两种计算屏幕宽高的方法,一种包含虚拟导航栏,一种不包含。
1 | fun getScreenHeight() = Resources.getSystem().displayMetrics.heightPixels |