支持刘海屏

试用 Compose 方式
Jetpack Compose 是推荐用于 Android 的界面工具包。了解如何在 Compose 中使用刘海屏。

刘海屏是某些设备上延伸到显示屏表面的一个区域。它可以提供无边框体验,同时为设备正面的重要传感器提供空间。

Android 支持在搭载 Android 9(API 级别 28)及更高版本的设备上使用刘海屏。不过,设备制造商也可以在搭载 Android 8.1 或更低版本的设备上支持刘海屏。

本文档介绍了如何为具有刘海屏的设备实现支持,包括如何使用刘海区域,即显示屏上包含刘海屏的无边框矩形。

图片:顶部中央的刘海屏示例
图 1. 1 刘海屏。

选择您的应用如何处理刘海区域

如果您不希望内容与刘海区域重叠,通常只需确保您的内容不与状态栏和导航栏重叠即可。如果您要渲染到刘海区域,请使用 WindowInsetsCompat.getDisplayCutout() 检索 DisplayCutout 对象,该对象包含每个刘海屏的安全边衬区和边界框。借助这些 API,您可以检查内容是否与刘海屏重叠,以便在需要时调整位置。

您还可以确定内容是否位于刘海区域后面。layoutInDisplayCutoutMode 窗口布局属性用于控制内容在刘海区域中的绘制方式。您可以将 layoutInDisplayCutoutMode 设置为以下值之一:

您可以通过编程方式设置刘海模式,也可以通过在 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 示例(处于竖屏模式):

一张图片,显示内容在竖屏模式下呈现到刘海区域中
图 2. 在竖屏模式下将内容渲染到刘海区域中。

下图是横屏设备的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 示例:

一张图片,显示内容在横屏模式下呈现到刘海区域中
图 3. 在横屏模式下将内容渲染到刘海区域中。

在此模式下,在竖屏和横屏模式下,窗口都会扩展到显示屏短边上的刘海屏下,无论窗口是否隐藏了系统栏。

边角上的凹口会被视为短边:

显示带有边角刘海屏的设备的图片
图 4. 带边角刘海屏的设备。

从不将内容呈现在刘海区域中

使用 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 时,绝不允许窗口与刘海区域重叠。

以下是纵向模式下的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 示例:

显示 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER(纵向)的图片
图 5. 竖屏模式的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 示例。

以下是横屏模式下的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 示例:

显示 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER(横向)的图片
图 6. 横屏模式下的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 示例。

支持刘海屏的最佳做法

使用刘海屏时,请考虑以下事项:

  • 请注意界面中关键元素的放置位置。不要让刘海区域遮盖任何重要的文本、控件或其他信息。
  • 不要将任何需要精细触摸识别的互动元素放置或扩展到刘海区域。刘海区域的触摸灵敏度可能较低。
  • 请尽可能使用 WindowInsetsCompat 检索状态栏高度,并确定要对内容应用的适当内边距。避免对状态栏高度进行硬编码,因为这可能会导致内容重叠或截断。

    图片:因边衬区设置不当而从顶部切断内容
    图 7.使用 WindowInsetsCompat 可避免内容重叠或截断。
  • 使用 View.getLocationInWindow() 确定应用使用了多少窗口空间。不要假定应用会使用整个窗口,也不要使用 View.getLocationOnScreen()

  • 如果您的应用需要进入和退出沉浸模式,请使用 shortEdgesnever 刘海模式。默认的刘海行为可能会导致应用中的内容在系统栏存在时显示在刘海区域中,但在沉浸模式下则不会。这会导致内容在过渡期间上下移动,如以下示例所示。

    显示内容在过渡期间上下移动的图片。
    图 8.内容在过渡期间上下移动的示例。
  • 在沉浸模式下,请谨慎使用窗口坐标与屏幕坐标,因为您的应用在进入信箱模式时不会占用整个屏幕。由于存在信箱模式,因此来自屏幕原点的坐标与基于窗口原点的坐标不同。您可以根据需要使用 getLocationOnScreen() 将屏幕坐标转换为视图的坐标。下图显示了内容为信箱模式时坐标的不同之处:

    显示内容为信箱模式时的窗口与屏幕坐标的图片。
    图 9.内容采用信箱模式时的窗口坐标与屏幕坐标。
  • 处理 MotionEvent 时,请使用 MotionEvent.getX()MotionEvent.getY() 来避免类似的坐标问题。请勿使用 MotionEvent.getRawX()MotionEvent.getRawY()

测试您的内容如何呈现

测试应用的所有屏幕和体验。如果可能,请在具有不同类型的刘海屏的设备上进行测试。如果您没有带刘海屏的设备,可以在搭载 Android 9 或更高版本的设备或模拟器上模拟常见的刘海屏配置,具体操作步骤如下:

  1. 启用开发者选项
  2. 开发者选项屏幕中,向下滚动到绘制部分,然后选择模拟刘海屏
  3. 选择刘海类型。

    该图片显示了如何在模拟器中模拟刘海屏
    图 10.开发者选项,用于测试内容的呈现方式。

其他资源