安全区适配
介绍
框架默认使用全局安全区进行页面内边距避让,避免内容被状态栏、刘海或导航条遮挡。安全区数据由 WindowAdapter 监听并写入全局状态,页面只需读取即可。
安全区监听与更新
安全区监听在 entry/src/main/ets/adapter/WindowAdapter.ets 中完成,应用启动时会初始化该适配器并监听系统避让区域变化,然后更新全局安全区状态。
核心流程:
- 通过
window.getWindowAvoidArea()读取系统与导航栏避让区域。 - 将 px 转换为 vp 后写入
WindowSafeAreaState。 - 监听
avoidAreaChange动态更新。
页面使用方式
AppNavDestination 默认启用安全区,会自动为页面加上内边距:
ts
import { AppNavDestination } from "ui";
import SafeAreaDemoViewModel from "../viewmodel/SafeAreaDemoViewModel";
/**
* @file 安全区示例页视图
*/
@ComponentV2
export struct SafeAreaDemoPage {
/**
* 安全区示例页 ViewModel
*/
@Local
private vm: SafeAreaDemoViewModel = new SafeAreaDemoViewModel();
/**
* 构建安全区示例页
* @returns {void} 无返回值
*/
build(): void {
AppNavDestination({
title: $r("app.string.demo_safe_area_title"),
viewModel: this.vm
}) {
Text("安全区示例");
};
}
}对应的 ViewModel:
ts
import { BaseViewModel } from "base";
/**
* @file 安全区示例页 ViewModel
*/
@ObservedV2
export default class SafeAreaDemoViewModel extends BaseViewModel {
}如果需要读取具体安全区值,可直接拿全局状态:
ts
import { getWindowSafeAreaState, WindowSafeAreaState } from "state";
/**
* @file 安全区数值读取示例
*/
@ComponentV2
export struct SafeAreaInsetSample {
/**
* 窗口安全区状态
*/
@Local
private windowSafeAreaState: WindowSafeAreaState = getWindowSafeAreaState();
/**
* 构建示例
* @returns {void} 无返回值
*/
build(): void {
Text(this.windowSafeAreaState.topInset.toFixed(2));
}
}覆盖默认安全区
AppNavDestination 内置安全区,如果你的页面需要自定义内边距(例如首页、沉浸式模块),可以关闭或覆盖:
ts
import { AppNavDestination } from "ui";
import MainViewModel from "../viewmodel/MainViewModel";
/**
* @file 主页面视图
*/
@ComponentV2
export struct MainPage {
/**
* 主页面 ViewModel
*/
@Local
private vm: MainViewModel = new MainViewModel();
/**
* 构建主页面
* @returns {void} 无返回值
*/
build(): void {
AppNavDestination({
title: $r("app.string.main_title"),
viewModel: this.vm,
safeAreaEnabled: false,
paddingValue: { top: 0, left: 0, right: 0, bottom: 0 }
}) {
Text("自定义安全区页面");
};
}
}API 说明
文件位置:core/state/src/main/ets/WindowSafeAreaState.ets
WindowSafeAreaState 属性
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
topInset | 顶部安全区高度(vp) | number | 0 |
leftInset | 左侧安全区宽度(vp) | number | 0 |
bottomInset | 底部安全区高度(vp) | number | 0 |
rightInset | 右侧安全区宽度(vp) | number | 0 |
WindowSafeAreaState 方法
| 方法 | 说明 | 参数 | 返回值 |
|---|---|---|---|
updateSafeArea | 更新安全区数据 | topInset: numberleftInset: numberbottomInset: numberrightInset: number | void |
updateSafeAreaByInsets | 使用结构体更新安全区 | insets: SafeAreaInsets | void |
全局函数
| 方法 | 说明 | 参数 | 返回值 |
|---|---|---|---|
getWindowSafeAreaState | 获取全局安全区状态 | - | WindowSafeAreaState |
注意事项
- 安全区是全局状态,单位为 vp。
- 默认情况下不需要手动处理安全区,
AppNavDestination已封装。 - 只有在沉浸式或自定义布局时才覆盖安全区设置。