刘海屏是某些设备上延伸到显示屏表面的一个区域。它可以提供无边框体验,同时为设备正面的重要传感器提供空间。
Android 支持在搭载 Android 9(API 级别 28)及更高版本的设备上使用刘海屏。不过,设备制造商也可以在搭载 Android 8.1 或更低版本的设备上支持刘海屏。
本文档介绍了如何为具有刘海屏的设备实现支持,包括如何使用刘海区域,即显示屏上包含刘海屏的无边框矩形。
选择您的应用如何处理刘海区域
如果您不希望内容与刘海区域重叠,通常只需确保您的内容不与状态栏和导航栏重叠即可。如果您要渲染到刘海区域,请使用 WindowInsetsCompat.getDisplayCutout()
检索 DisplayCutout
对象,该对象包含每个刘海屏的安全边衬区和边界框。借助这些 API,您可以检查内容是否与刘海屏重叠,以便在需要时调整位置。
您还可以确定内容是否位于刘海区域后面。layoutInDisplayCutoutMode
窗口布局属性用于控制内容在刘海区域中的绘制方式。您可以将 layoutInDisplayCutoutMode
设置为以下值之一:
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
:在竖屏模式下显示时,内容会呈现到刘海区域中,但在横屏模式下显示时,内容会进入信箱模式。LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
:在竖屏和横屏模式下,内容都会呈现到刘海区域中。LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
:内容绝不会呈现到刘海区域中。
您可以通过编程方式设置刘海模式,也可以通过在 activity 中设置样式来设置。以下示例定义了将 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
属性应用于 activity 的样式。
<style name="ActivityTheme"> <item name="android:windowLayoutInDisplayCutoutMode"> shortEdges <!-- default, shortEdges, or never --> </item> </style>
以下部分更详细地介绍了不同的刘海模式。
默认行为
默认情况下,在未设置特殊标志的竖屏模式下,在带有刘海屏的设备上,状态栏的大小会调整为至少与刘海一样高,并且您的内容会显示在下方区域。在横屏模式或全屏模式下,您的应用窗口会进入信箱模式,这样您的内容都不会显示在刘海区域中。
将内容呈现在短边刘海区域中
对于某些内容(如视频、照片、地图和游戏),在刘海区域中渲染是为用户提供更具沉浸感的无边框体验的绝佳方式。使用 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
时,无论系统栏处于隐藏还是可见状态,在竖屏和横屏模式下,内容都会延伸到屏幕短边上的刘海区域。使用此模式时,请确保没有重要内容与刘海区域重叠。
下图是设备的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
示例(处于竖屏模式):
下图是横屏设备的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
示例:
在此模式下,在竖屏和横屏模式下,窗口都会扩展到显示屏短边上的刘海屏下,无论窗口是否隐藏了系统栏。
边角上的凹口会被视为短边:
从不将内容呈现在刘海区域中
使用 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
时,绝不允许窗口与刘海区域重叠。
以下是纵向模式下的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
示例:
以下是横屏模式下的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
示例:
支持刘海屏的最佳做法
使用刘海屏时,请考虑以下事项:
- 请注意界面中关键元素的放置位置。不要让刘海区域遮盖任何重要的文本、控件或其他信息。
- 不要将任何需要精细触摸识别的互动元素放置或扩展到刘海区域。刘海区域的触摸灵敏度可能较低。
请尽可能使用
WindowInsetsCompat
检索状态栏高度,并确定要对内容应用的适当内边距。避免对状态栏高度进行硬编码,因为这可能会导致内容重叠或截断。使用
View.getLocationInWindow()
确定应用使用了多少窗口空间。不要假定应用会使用整个窗口,也不要使用View.getLocationOnScreen()
。如果您的应用需要进入和退出沉浸模式,请使用
shortEdges
或never
刘海模式。默认的刘海行为可能会导致应用中的内容在系统栏存在时显示在刘海区域中,但在沉浸模式下则不会。这会导致内容在过渡期间上下移动,如以下示例所示。在沉浸模式下,请谨慎使用窗口坐标与屏幕坐标,因为您的应用在进入信箱模式时不会占用整个屏幕。由于存在信箱模式,因此来自屏幕原点的坐标与基于窗口原点的坐标不同。您可以根据需要使用
getLocationOnScreen()
将屏幕坐标转换为视图的坐标。下图显示了内容为信箱模式时坐标的不同之处:处理
MotionEvent
时,请使用MotionEvent.getX()
和MotionEvent.getY()
来避免类似的坐标问题。请勿使用MotionEvent.getRawX()
或MotionEvent.getRawY()
,
测试您的内容如何呈现
测试应用的所有屏幕和体验。如果可能,请在具有不同类型的刘海屏的设备上进行测试。如果您没有带刘海屏的设备,可以在搭载 Android 9 或更高版本的设备或模拟器上模拟常见的刘海屏配置,具体操作步骤如下:
- 启用开发者选项。
- 在开发者选项屏幕中,向下滚动到绘制部分,然后选择模拟刘海屏。
选择刘海类型。