支持显示切口

尝试 Compose 方法
Jetpack Compose 是 Android 推荐的 UI 工具包。了解如何在 Compose 中使用显示切口。

一个 显示切口 是某些设备上延伸到显示屏表面的区域。它允许边缘到边缘的体验,同时为设备正面重要的传感器提供空间。

Android 在运行 Android 9(API 级别 28)或更高版本的设备上支持显示切口。但是,设备制造商也可以在运行 Android 8.1 或更低版本的设备上支持显示切口。

本文档介绍如何实现对带有切口的设备的支持,包括如何使用切口区域——即包含切口的显示屏表面上的边缘到边缘矩形。

An image showing an example of top-center display cutout
图 1. 1 显示切口。

选择您的应用如何处理切口区域

如果您不希望您的内容与切口区域重叠,通常只需确保您的内容不会与状态栏和导航栏重叠即可。如果您正在渲染到切口区域,请使用 WindowInsetsCompat.getDisplayCutout() 获取一个 DisplayCutout 对象,该对象包含每个切口的安全内边距和边界框。这些 API 允许您检查您的内容是否与切口重叠,以便您在需要时重新定位。

您还可以确定内容是否在切口区域后面布局。该 layoutInDisplayCutoutMode 窗口布局属性控制您的内容如何在切口区域中绘制。您可以将 layoutInDisplayCutoutMode 设置为以下值之一

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:当显示切口包含在系统栏中时,内容将渲染到切口区域。否则,窗口不会与显示切口重叠;例如,内容在横向模式下显示时可能会被信箱化。如果您的应用针对 SDK 35,则对于非浮动窗口,这将被解释为 ALWAYS
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS:内容始终可以延伸到切口区域。如果您的应用针对 SDK 35 并在 Android 15 设备上运行,则对于非浮动窗口,这是唯一允许的模式,以确保边缘到边缘的显示。
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES:内容在纵向和横向模式下都渲染到切口区域。不要用于浮动窗口。如果您的应用针对 SDK 35,则对于非浮动窗口,这将被解释为 ALWAYS
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:内容永远不会渲染到切口区域。如果您的应用针对 SDK 35,则对于非浮动窗口,这将被解释为 ALWAYS

您可以以编程方式设置切口模式,也可以通过在您的活动中设置 样式 来设置。以下示例定义了一种样式,将 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 属性应用于活动。

<style name="ActivityTheme">
  <item name="android:windowLayoutInDisplayCutoutMode">
    shortEdges <!-- default, shortEdges, or never -->
  </item>
</style>

以下部分将更详细地描述不同的切口模式。

默认行为

如果您的应用针对 SDK 35 并在 Android 15 设备上运行,LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS 是默认行为,而 LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 将被解释为 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS,用于非浮动窗口。

否则,LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 是默认值。

在短边切口区域中渲染内容

如果您的应用针对 SDK 35 并在 Android 15 设备上运行,LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 将被解释为 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS,用于非浮动窗口。

使用 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES,内容会延伸到显示屏短边上的切口区域,无论系统栏是隐藏还是可见。使用此模式时,请确保没有任何重要内容与切口区域重叠。

下图是 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 在纵向设备上的示例

An image showing content rendering into the cutout area while in portrait mode
图 2. 内容在纵向模式下渲染到切口区域。

下图是 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 在横向设备上的示例

An image showing content rendering into the cutout area while in landscape mode
图 3. 内容在横向模式下渲染到切口区域。

在此模式下,窗口会延伸到显示屏短边上的切口下方,无论纵向还是横向,无论窗口是否隐藏系统栏。

角落的切口被认为是在短边上

An image showing a device with a corner cutout
图 4. 具有角落切口的设备。

永远不要在显示切口区域中渲染内容

如果您的应用针对 SDK 35 并在 Android 15 设备上运行,LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 将被解释为 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS,用于非浮动窗口。

使用 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER,窗口永远不允许与切口区域重叠。

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

An image showing the LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER for portrait
图 5. LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 在纵向模式下的示例。

以下是 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 在横向模式下的示例

An image showing the LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER for landscape
图 6. LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 在横向模式下的示例。

显示切口支持的最佳实践

在处理显示切口时,请考虑以下几点

  • 注意 UI 关键元素的放置。不要让切口区域遮挡任何重要的文本、控件或其他信息。
  • 不要将需要精细触摸识别的任何交互式元素放置在或延伸到切口区域。切口区域的触摸灵敏度可能较低。
  • 如果可能,请使用 WindowInsetsCompat 获取状态栏高度并确定要应用于您的内容的适当填充。避免硬编码状态栏高度,因为这会导致内容重叠或被剪切。

    An image showing content cut at the top for improper insets setup
    图 7. 使用 WindowInsetsCompat 避免内容重叠或被剪切。
  • 使用 View.getLocationInWindow() 确定您的应用使用了多少窗口空间。不要假设应用使用了整个窗口,也不要使用 View.getLocationOnScreen().

  • 如果您的应用需要在沉浸式模式之间进行转换,请使用 alwaysshortEdgesnever 切口模式。默认的切口行为会导致您的应用中的内容在系统栏存在时渲染到切口区域,但在沉浸式模式下不会。这会导致内容在转换过程中上下移动,如以下示例所示。

    An image showing content moving up and down during transitions.
    图 8. 内容在转换过程中上下移动的示例。
  • 在沉浸式模式下,在使用窗口坐标和屏幕坐标时要小心,因为您的应用在信箱化时不会使用整个屏幕。由于信箱的存在,屏幕原点的坐标与窗口原点的坐标不同。您可以使用 getLocationOnScreen() 将屏幕坐标转换为视图坐标。下图显示了内容信箱化时坐标有何不同

    An image showing window versus screen coordinates when content is letterboxed.
    图 9. 内容信箱化时的窗口坐标与屏幕坐标。
  • 处理 MotionEvent 时,请使用 MotionEvent.getX()MotionEvent.getY() 避免类似的坐标问题。不要使用 MotionEvent.getRawX()MotionEvent.getRawY().

测试您的内容如何渲染

测试您的应用的所有屏幕和体验。如果可能,请在具有不同切口类型的设备上进行测试。如果您没有带有切口的设备,您可以在运行 Android 9 或更高版本的任何设备或模拟器上模拟常见的切口配置,方法是执行以下操作

  1. 启用 开发者选项.
  2. 开发者选项屏幕中,向下滚动到绘图部分,然后选择模拟带切口的显示屏
  3. 选择切口类型。

    An image showing how to simulate a display cutout in the emulator
    图 10. 开发者选项,用于测试内容的呈现方式。

其他资源