支持刘海屏

试用 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.用于测试内容的呈现方式的开发者选项。

其他资源