android9模拟刘海屏,刘海屏  |  Android 开源项目  |  Android Open Source Project

Android 9 新增了对在设备上实现不同类型刘海屏的支持。通过刘海屏,您可以打造沉浸式全面屏体验,同时继续在设备前端为重要传感器留出空间。

d79f1c1f7560c7b2e4f74e496813aaf1.png

图 1. 顶部中间刘海屏

Android 9 支持以下类型的刘海屏:

顶部中间刘海屏:刘海屏位于顶部边缘的中间位置

顶部非中间刘海屏:刘海屏位于边角处或稍微偏离中心的位置

底部刘海屏:刘海屏位于底部

双刘海屏:一个刘海屏位于顶部,一个位于底部

示例和源代码

以下窗口管理器代码 (PhoneWindowManager.java) 显示了如何在未设置 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS 的情况下将显示帧嵌入安全区域。

// Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in

// the cutout safe zone.

if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {

final Rect displayCutoutSafeExceptMaybeBars = mTmpDisplayCutoutSafeExceptMaybeBarsRect;

displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);

if (layoutInScreen && layoutInsetDecor && !requestedFullscreen

&& cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {

// At the top we have the status bar, so apps that are

// LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN

// already expect that there's an inset there and we don't need to exclude

// the window from that area.

displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;

}

if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation

&& cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {

// Same for the navigation bar.

switch (mNavigationBarPosition) {

case NAV_BAR_BOTTOM:

displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;

break;

case NAV_BAR_RIGHT:

displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;

break;

case NAV_BAR_LEFT:

displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;

break;

}

}

if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {

// The IME can always extend under the bottom cutout if the navbar is there.

displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;

}

// Windows that are attached to a parent and laid out in said parent already avoid

// the cutout according to that parent and don't need to be further constrained.

// Floating IN_SCREEN windows get what they ask for and lay out in the full screen.

// They will later be cropped or shifted using the displayFrame in WindowState,

// which prevents overlap with the DisplayCutout.

if (!attachedInParent && !floatingInScreenWindow) {

mTmpRect.set(pf);

pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);

parentFrameWasClippedByDisplayCutout |= !mTmpRect.equals(pf);

}

// Make sure that NO_LIMITS windows clipped to the display don't extend under the

// cutout.

df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);

}

SystemUI 在刘海屏区域呈现,且需要确定可以绘制的位置。

PhoneStatusBarView.java 提供了一个视图示例,它确定了刘海屏的位置、刘海屏大小,以及从导航栏嵌入是否可以避开刘海屏区域。

通过覆盖 onApplyWindowInsets()onApplyWindowInsets(),视图可以确定刘海屏的位置,并相应地更新其布局。

@Override

public WindowInsets onApplyWindowInsets(WindowInsets insets) {

if (updateOrientationAndCutout(mLastOrientation)) {

updateLayoutForCutout();

requestLayout();

}

return super.onApplyWindowInsets(insets);

}

这些方法概述了各种类型的刘海屏(即顶部中间刘海屏、顶部非中间刘海屏、底部刘海屏和双刘海屏)在状态栏中的处理方式。

要求

要确保刘海屏不会对应用造成负面影响,您必须确保:

在竖屏模式下,状态栏的高度至少与刘海屏的高度持平

在全屏模式和横屏模式下,刘海屏区域必须显示遮幅式黑边

您的设备最多可以在每个短边处(顶部和底部)各设一个刘海屏。

如需了解详情,请参阅 CDD。

注意:对于面向 Android 8.0 或更低版本的应用,您可以为用户提供一个可使全屏或横屏应用延伸至刘海屏区域的选项(例如导航栏中的切换开关)。由于这样做可能会导致内容被切断,因此 layoutInDisplayCutoutModelayoutInDisplayCutoutMode 活动主题属性已反向移植到 Android 8.1,以允许应用选择停用该选项。如果您设置了该属性,则可能无法显示特殊的模式切换开关。

实现

要在设备上实现刘海屏,您必须为系统界面配置以下值。

说明

quick_qs_offset_height

定义“快捷设置”面板的上外边距。时钟和电池图标显示在该面板上方的空间。

在 values-land 中,设置为 status_bar_height_landscape,在纵屏中,将此值设置为默认值 48dp 或刘海屏高度(以较大者为准)。可以根据需要选择高于刘海屏的高度。

quick_qs_total_height

展开通知栏时,“超快设置”面板(收起的“快捷设置”面板)的总高度(其中包括包含时钟图标的面板上方的空间)。

由于快捷设置的布局方式,“超快设置”面板(包括偏移量)的总高度必须是静态已知的,因此该值必须使用相同的增量

quick_qs_offset_height。在 Values-land 中,此值默认为 152dp,在纵屏模式下,此值默认为 176dp。

status_bar_height_portrait

从框架的角度而言,状态栏的默认高度。

在大多数设备上,此值默认为 24dp。如果设备上有刘海屏,则将此值设置为刘海屏的高度。可以根据需要选择高于刘海屏的高度。

status_bar_height_landscape

状态栏在横屏模式下的高度。由于仅支持在设备的短边上显示刘海屏,因此此值始终是未经更改的状态栏高度。

在没有刘海屏的设备上,此值等同于 status_bar_height_portrait。如果设备上有刘海屏,则将此值保留为默认的状态栏高度。

config_mainBuiltInDisplayCutout

用于定义刘海屏形状的路径。这是可由 android.util.PathParser 解析的字符串,这也是系统如何定义刘海的大小和形状。

可在路径中指定 @dp@dp 以便模拟针对不同设备的形状。由于实际的刘海屏具有精确的像素尺寸,因此在定义硬件刘海屏的路径时,请勿使用 @dp@dp 指定符。

config_fillMainBuiltinDisplayCutout

一个确定是否在软件中绘制刘海屏路径(在上文中进行了定义)的布尔值。可用于模拟刘海屏,或填充实际刘海屏,以实现抗锯齿。

如果为 true,则系统会以黑色填充 config_mainBuiltInDisplayCutout。

如需了解默认定义,请参阅以下 dimens 文件:

模拟刘海屏的示例叠加层:

M 0,0

L -48, 0

L -44.3940446283, 36.0595537175

C -43.5582133885, 44.4178661152 -39.6, 48.0 -31.2, 48.0

L 31.2, 48.0

C 39.6, 48.0 43.5582133885, 44.4178661152 44.3940446283, 36.0595537175

L 48, 0

Z

@dp

true

48dp

28dp

48dp

176dp

验证

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值