鸿蒙开发-安全区域和窗口沉浸式实现
文章摘要:安全区域是页面显示区域,默认不与系统避让区重叠。开发者可通过expandSafeArea属性扩展组件绘制至安全区外,或通过setKeyboardAvoidMode配置键盘避让模式。实现沉浸式效果有组件级和窗口级两种方案:组件级通过background()、ignoreLayoutSafeArea()或expandSafeArea实现局部扩展;窗口级通过setWindowLayoutFul
安全区域
安全区域是指页面的显示区域,默认情况下开发者开发的界面都布局在安全区域内,不与系统设置的避让区比如状态栏、导航栏区域重叠。提供属性方法允许开发者设置组件绘制内容突破安全区域的限制,通过expandSafeArea属性支持组件不改变布局情况下扩展其绘制区域至安全区外,通过设置setKeyboardAvoidMode来配置虚拟键盘弹出时页面的避让模式。页面中有标题栏等文字不希望和避让区重叠时,建议对组件设置expandSafeArea属性实现沉浸式效果,也可以直接通过窗口接口setWindowLayoutFullScreen设置全屏沉浸式。
expandSafeArea
控制组件扩展其安全区域
说明
-
设置expandSafeArea属性进行组件绘制扩展时,建议组件尺寸不要设置固定宽高(百分比除外),当设置固定宽高(包括设置'auto')时,扩展安全区域的方向只支持[SafeAreaEdge.TOP, SafeAreaEdge.START],扩展后的组件尺寸保持不变。
-
安全区域不会限制内部组件的布局和大小,不会裁剪内部组件。
-
当父容器为滚动容器时,组件设置expandSafeArea属性后,自身不会延伸,但仍可触发其子节点中设置了expandSafeArea的延伸范围更新。
-
设置expandSafeArea()时,不传参,走默认值处理;设置expandSafeArea([],[])时,相当于入参是空数组,此时expandSafeArea属性设置无效。
-
组件设置expandSafeArea生效的条件为:
1.type为SafeAreaType.KEYBOARD时默认生效,表现为组件不避让键盘。
2.设置其他type,组件的边界与安全区域重合时组件能够延伸到安全区域下。例如:设备顶部状态栏高度100,那么组件在屏幕中的绝对位置需要为0 <= y <= 100。
-
组件延伸到避让区时,在避让区的事件如点击事件等可能会被系统拦截,优先给状态栏等系统组件响应。
-
滚动类容器内的组件不建议设置expandSafeArea属性,如果设置,需要按照组件嵌套关系,将当前节点到滚动类祖先容器间所有直接节点设置expandSafeArea属性,否则expandSafeArea属性在滚动后可能会失效,写法参考示例7。
-
expandSafeArea属性仅作用于当前组件,不会向父组件或子组件传递,因此使用过程中,所有相关组件均需配置。
-
同时设置expandSafeArea和position属性时,position属性会优先生效,expandSafeArea属性会后生效。对于未设置position、offset等绘制属性的组件,如果其边界未与避让区重叠,设置expandSafeArea属性将不生效,如弹窗和半模态组件。
-
对于expandSafeArea属性无法生效的场景,若要将组件部署在避让区,需要手动调整组件的坐标。
setKeyboardAvoidMode
KeyboardAvoidMode.RESIZE模式会压缩页面大小,页面中设置百分比宽高的组件会跟随页面压缩,而直接设置宽高的组件会按设置的固定大小布局。设置KeyboardAvoidMode的RESIZE模式时,expandSafeArea([SafeAreaType.KEYBOARD],[SafeAreaEdge.BOTTOM])不生效。
KeyboardAvoidMode.NONE模式配置页面不避让键盘,页面会被抬起的键盘遮盖。
setKeyboardAvoidMode针对页面生效,对于弹窗类组件不生效,比如Dialog、Popup、Menu、BindSheet、BindContentCover、Toast、OverlayManager。弹窗类组件的避让模式可以参考CustomDialogControllerOptions对象说明。
ignoreLayoutSafeArea
忽略布局安全区边缘的组件,如果其宽度或高度设置了LayoutPolicy.matchParent,其大小和位置都会改变,否则仅改变其位置。
依据safeAreaPadding累积功能,组件可扩展其安全区边缘到所有能感知的连续安全区域。
滚动类组件的子元素忽略布局安全区边缘时在滚动方向不考虑滚动组件自身及其父组件的安全区域,包括:List、ArcListItem、Grid、WaterFlow、Swiper和Tabs。
忽略布局安全区属性.ignoreLayoutSafeArea和忽略渲染安全区属性.expandSafeArea都设置时,.ignoreLayoutSafeArea先生效,.expandSafeArea在前者基础上再生效。
沉浸式实现主要考虑如下两个因素:
- 实现沉浸式效果:通过特定方法、属性或接口,使页面突破安全区或标题栏限制,延伸至目标区域。
页面沉浸式效果实现方案分为窗口、组件两个层级:
- 窗口级:应用级全局沉浸,作用于所有页面。
- 组件级:作用于当前组件,可针对单个页面内的多个组件分别配置。
- 避让处理:避免页面内容与避让区的系统信息(如电量、时间)、交互功能(如导航条手势)或窗口控制键(如关闭、最小化)发生遮挡和冲突。
组件设置背景沉浸(组件级)
组件与避让区边界重合时,设置组件的background()属性,将组件背景扩展至避让区,页面布局仍在安全区内
Column() {
// ...
}
.background('#F1F3F5')
组件设置页面沉浸(组件级)
通过设置ignoreLayoutSafeArea()并设置高度为LayoutPolicy.matchParent适应父组件,页面背景与布局均扩展至顶部状态栏和底部导航条。作为组件级的沉浸式方案,每个页面均需单独配置。当页面内容与避让区发生冲突时,需由开发者手动进行避让处理。
Column() {
// ...
}
// Expands the layout safe area of a component.
.ignoreLayoutSafeArea()
.height(LayoutPolicy.matchParent)
安全区域拓展(组件级)
设置组件的expandSafeArea属性,将组件的安全区域延伸至状态栏或导航条区域,同时保持子组件在安全区内布局,无需额外避让处理。支持指定系统避让区域类型(SafeAreaType)和延伸方向(SafeAreaEdge),实现沉浸式的方案可参考组件安全区方案。
Row() {
Image('https://gips3.baidu.com/it/u=3886271102,3123389489&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960')
.width('100%')
.height('100%')
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
}.height('100%')
窗口设置沉浸式显示(窗口级)
调用窗口强制全屏布局接口setWindowLayoutFullScreen()设置窗口为沉浸式布局。页面布局范围从安全区域扩展为整个窗口(包括状态栏和导航条),布局范围扩展效果同组件设置页面沉浸。
该方案为窗口级沉浸方案,沉浸式布局生效时,所有页面均开启全屏模式,需要开发者在各页面进行避让处理。
windowClass.setWindowLayoutFullScreen(true).catch((err: BusinessError) => {
console.error(`Failed to set full screen mode. Code: ${err.code}, message: ${err.message}`);
|
对比维度 |
组件设置背景沉浸 |
组件设置页面沉浸 |
安全区域拓展 |
窗口设置沉浸式显示 |
|---|---|---|---|---|
|
级别 |
组件级 |
组件级 |
组件级 |
窗口级 |
|
特点 |
仅背景扩展至避让区,内容默认在安全区 |
背景与内容均扩展至避让区 |
仅背景扩展至避让区,内容默认在安全区 支持指定系统避让区域类型和延伸方向 |
所有页面布局范围扩展至全屏,不自动避让 |
|
使用场景 |
仅页面背景沉浸的场景 |
需组件内容完全覆盖屏幕的场景 |
需要指定延伸区域类型的局部延伸场景 |
应用所有页面均需实现沉浸式 |
|
优点 |
使用简单,易理解 一次配置适配不同窗口模式、窗口方向 支持多组件不同背景扩展 |
使用简单,易理解 一次配置适配不同窗口模式、窗口方向 |
能够对扩展不同的安全区域进行配置 子组件仍在安全区内布局,无需额外的避让处理 |
全局统一生效,适配逻辑集中 |
|
缺点 |
滚动内容无法延伸至避让区 需为每个页面单独配置 |
内容易与避让区元素冲突,需手动处理避让 需为每个页面单独配置 |
滚动内容无法延伸至避让区 参数复杂,理解成本过高 |
需手动计算避让区高度,处理所有内容避让 |
避让处理
由于避让区本身有内容展示(如状态栏中的电量、时间等系统信息),或是手势交互(如导航条点击或上滑),在实现应用页面沉浸式效果后,往往会和避让区域产生UI元素的遮挡、视觉上的违和或交互上的冲突等问题,开发者可以针对不同场景选择合适的方式进行适配。
- 使用Window.setWindowSystemBarEnable()方法或Window.setSpecificSystemBarEnabled()方法设置状态栏和导航条的显隐。
- 使用Window.getWindowAvoidArea()方法获取避让区域的高度,设置应用页面内容的上下padding实现避让状态栏和导航条。
- 使用on('avoidAreaChange')动态监听避让区变化。
- 通过AvoidAreaType.TYPE_SYSTEM获取状态栏区域信息。
- 通过AvoidAreaType.TYPE_NAVIGATION_INDICATOR获取底部导航条区域信息。
- 通过AvoidAreaType.TYPE_CUTOUT获取挖孔区信息。
更多推荐

所有评论(0)