刘海屏是某些设备上延伸到显示屏表面的区域。它可以实现无边框体验,同时在设备正面为重要传感器提供空间。
Android 在搭载 Android 9(API 级别 28)及更高版本的设备上支持刘海屏。不过,设备制造商也可以在搭载 Android 8.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
。
您可以通过编程方式或在 activity 中设置样式来设置刘海模式。以下示例定义了一个样式,用于将 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
属性应用于 activity。
<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
示例:
下图是设备的横向 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
示例:
在此模式下,无论窗口是否隐藏了系统栏,在纵向和横向模式下,窗口都会在显示屏短边的刘海下扩展。
边角处的刘海屏被视为位于短边上:
从不将内容呈现在刘海区域中
如果您的应用以 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
示例:
以下是横屏模式下的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
示例:
支持刘海屏的最佳做法
使用刘海屏时,请注意以下几点:
- 请注意界面中关键元素的放置位置。不要让刘海区域遮盖任何重要的文本、控件或其他信息。
- 不要将任何需要精细触摸识别的互动元素放置或扩展到刘海区域。刘海区域中的触控灵敏度可能较低。
请尽可能使用
WindowInsetsCompat
检索状态栏高度,并确定适用于内容的适当内边距。避免对状态栏高度进行硬编码,因为这样做可能会导致内容重叠或被截断。使用
View.getLocationInWindow()
确定应用当前使用了多少窗口空间。不要假定应用会使用整个窗口,也不要使用View.getLocationOnScreen()
。如果您的应用需要进入和退出沉浸模式,请使用
always
、shortEdges
或never
刘海模式。默认的刘海行为可能会导致应用中的内容在显示系统栏时呈现在刘海区域中,但在沉浸模式下则不会。这会导致内容在过渡期间上下移动,如以下示例所示。在沉浸模式下,请谨慎使用窗口坐标与屏幕坐标,因为您的应用在进入信箱模式时不会占用整个屏幕。由于存在信箱模式,基于屏幕原点的坐标与基于窗口原点的坐标不同。您可以根据需要使用
getLocationOnScreen()
将屏幕坐标转换为视图的坐标。下图显示了内容为信箱模式时坐标有何不同:处理
MotionEvent
时,请使用MotionEvent.getX()
和MotionEvent.getY()
来避免类似的坐标问题。不要使用MotionEvent.getRawX()
或MotionEvent.getRawY()
。
测试您的内容如何呈现
测试应用的所有屏幕和体验。如果可能,请在具有不同类型刘海屏的设备上进行测试。如果您没有带刘海屏的设备,可以在搭载 Android 9 或更高版本的设备或模拟器上模拟常见的刘海配置,具体操作步骤如下:
- 启用开发者选项。
- 在开发者选项屏幕中,向下滚动到绘图部分,然后选择模拟刘海屏。
选择刘海类型。
其他资源
- LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
- LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
- LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
- LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT