HarmonyOS 鸿蒙Next区域避让开发指导
HarmonyOS 鸿蒙Next区域避让开发指导
一、概述
在移动应用开发中,不同设备的屏幕形态各异,如刘海屏、全面屏、折叠屏等,同时系统状态栏、导航栏、软键盘等元素也会占据屏幕空间。为了确保应用内容在各种设备和场景下都能正常显示,不被遮挡,RN、Flutter和H5提供了一系列区域避让的机制和接口。此外,随着折叠屏设备逐渐普及,为了让应用在折叠屏设备上提供良好的用户体验,需要对布局进行特殊处理,RN和Flutter为此推出了折叠屏布局专用组件:FolderStack和FoldSplitContainer。本文将详细介绍各个框架区域避让和折叠屏布局组件的实现原理、适配指导以及具体的场景案例。
使用场景
典型应用全屏窗口UI元素包括状态栏、应用界面和底部导航条,其中状态栏和导航条,通常在全屏沉浸式布局下称为避让区,避让区之外的区域称为安全区。界面元素在不同设备上存在差异,下面是不同设备上状态栏、挖孔区、导航栏的位置差异,包括:直板机、PAD、PC、折叠屏(小折叠、双折、三折)。
说明
下图中标记区域含义:1为状态栏、2为挖孔区、3为导航栏。
图1 直板机界面元素示意图
图2 PAD界面元素示意图
图3 PC界面元素示意图
图4 折叠屏–小折叠 界面元素示意图(左图展开态 右图折叠态)
图5 折叠屏–双折叠 界面元素示意图(左图折叠态 右图展开态)
图6 折叠屏–三折叠 界面元素示意图(左图折叠态 右图二屏折叠态 下图三屏全展开态)
面对上述不同设备的避让区差异,可以按照如下三种场景实现应用沉浸式效果:
1.1 安全区布局场景
布局系统保持安全区内布局,确保应用内容不会延伸到状态栏、导航栏区域。
1.2 安全区布局+背景沉浸模式
布局系统保持安全区内布局,然后延伸绘制内容(如背景色、背景图)到状态栏和导航条区域,实现沉浸式效果。
1.3 全屏布局+避让场景
布局系统保持全屏布局,通过相关接口获取避让区域位置、大小等信息,调整元素位置,确保不会被避让区遮挡。
二、实现原理
2.1 RN 区域避让实现原理
区域避让主要借助AvoidArea接口提供的能力实现,该接口由@hadss/react_native_avoid_area库提供。该接口包含几个核心方法,用于处理与区域避让相关的操作。在不同平台上,这些方法的实现和使用存在差异。
getWindowAvoidArea
此方法接收一个AvoidAreaType避让区域类型的参数,通过该参数可以获取当前应用窗口内容需要规避的区域。这些区域可能包括系统栏、刘海屏、手势操作区、软键盘等与窗口内容重叠时需要避让的区域。接口返回信息中包含对应避让区域是否可见、位置信息及宽高信息,应用可以通过这些信息调整内容布局,避免内容被遮挡。
接口返回信息结构如下:
{
"visible": true, // 是否遮挡布局
"leftRect": { // 左侧避让区域
"left": 0, // 距离左侧的边距
"top": 0, // 距离上方的边距
"width": 0, // 避让区域宽度
"height": 0 // 避让区域高度
},
"topRect": { // 上方避让区域
// 结构与leftRect相同
},
"rightRect": { // 右侧避让区域
// 结构与leftRect相同
},
"bottomRect": { // 下方避让区域
// 结构与leftRect相同
}
}
接口使用示例如下:
// AvoidArea避让区域信息,AvoidAreaType避让区域类型
import { AvoidArea, AvoidAreaType } from "@hadss/react_native_avoid_area/src/turbo/NativeAvoidModule";
// AvoidArea API
import { Avoid } from '@hadss/react_native_avoid_area/src/index'
// 获取避让区域
let avoidArea = Avoid.getWindowAvoidArea(type);
addAvoidAreaListener
该方法用于添加系统规避区变化事件的监听。当系统规避区发生变化时,如软键盘弹出或收起、设备旋转等,会触发相应的回调函数,应用可以在回调中更新布局。使用示例如下:
// AvoidArea避让区域信息,AvoidAreaType避让区域类型
import { AvoidArea, AvoidAreaType } from "@hadss/react_native_avoid_area/src/turbo/NativeAvoidModule";
// AvoidArea API
import { Avoid } from '@hadss/react_native_avoid_area/src/index'
// 添加系统规避区变化事件的监听
Avoid.addAvoidAreaListener(data => {
// 开发者基于AvoidAreaType自行逻辑处理
});
removeAvoidAreaListener
用于移除之前添加的系统规避区变化事件监听,避免不必要的回调触发,节省系统资源。使用示例如下:
// AvoidArea API
import { Avoid } from '@hadss/react_native_avoid_area/src/index';
// 移除系统规避区变化事件的监听
Avoid.removeAvoidAreaListener();
2.2 Flutter 区域避让实现原理
区域避让主要借助 AvoidAreaApi 这个对外提供能力的接口来实现。该接口包含几个核心方法,用于处理与区域避让相关的操作。
getWindowAvoidArea
此方法接收一个AvoidAreaType类型的参数,通过该参数可以获取当前应用窗口内容需要规避的区域。这些区域可能包括系统栏、刘海屏、手势操作区、软键盘等与窗口内容重叠时需要避让的区域。例如,在处理刘海屏设备时,应用可以通过该方法获取刘海屏区域的信息,从而调整内容布局,避免内容被刘海遮挡。
// packages/avoid_area/ohos/src/main/ets/hadss/avoid_area/AvoidAreaPlugin.ets
getWindowAvoidArea(type: window.AvoidAreaType, result: MethodResult) {
const windowAvoidArea = this.windowClass?.getWindowAvoidArea(type ?? window.AvoidAreaType.TYPE_SYSTEM);
result.success(JSON.stringify(windowAvoidArea));
}
addAvoidAreaListener
该方法用于添加系统规避区变化事件的监听。当系统规避区发生变化时,如软键盘弹出或收起、设备旋转等,会触发相应的回调函数,应用可以在回调中更新布局。
// packages/avoid_area/ohos/src/main/ets/hadss/avoid_area/AvoidAreaPlugin.ets
addAvoidAreaListener(eventSink?: EventSink) {
this.windowClass?.on('avoidAreaChange', (avoidAreaOptions: window.AvoidAreaOptions) => {
eventSink?.success(JSON.stringify(avoidAreaOptions))
})
}
removeAvoidAreaListener
用于移除之前添加的系统规避区变化事件监听,避免不必要的回调触发,节省系统资源。
// packages/avoid_area/ohos/src/main/ets/hadss/avoid_area/AvoidAreaPlugin.ets
removeAvoidAreaListener() {
this.windowClass?.off('avoidAreaChange');
}
2.3 Flutter 折叠屏布局组件实现原理
FoldSplitContainer
定义了 FoldSplitContainer 组件,用于实现折叠屏二分栏、三分栏在展开态、悬停态以及折叠态的区域控制。
- 状态监听:通过 FolderStackPlugin.folderStateEvents 监听折叠屏状态变化,当状态变化时更新界面。
- 布局构建:根据不同的折叠屏状态(展开、半折叠、折叠)调用不同的布局构建方法,如 _buildExpandedLayout、_buildHoverModeLayout 和 _buildFoldedRegionLayout。
- 比例转换:通过 _ratioToFlex 方法将比例转换为整数 flex 因子,用于 Flex 组件的布局。
FolderStack
定义了 FolderStack 组件,继承于 Stack 控件,新增了折叠屏悬停能力,通过识别 upperItems 自动避让折叠屏折痕区后移到上半屏。
- 状态监听:同样通过 FolderStackPlugin.folderStateEvents 监听折叠屏状态变化。
- 布局处理:当设备处于半折叠且折痕方向为水平时,将 upperItems 中的子组件堆叠到上半屏,其他组件堆叠在下半屏。
- 上下屏:通过折痕区域范围算出上下屏占用比例,然后使用 Flex 组件的布局。
- **文件实现了折叠屏状态的监听功能,当折叠屏状态变化时,将状态信息通过 EventSink 发送给 Flutter 端。
接口桥接和公用封装主要在 folder_options.dart 和 folder_plugin.dart 中实现。
2.4 H5 区域避让实现原理
区域避让主要通过原生接口提供的能力实现,该接口包含几个核心方法,用于处理与区域避让相关的操作。
avoidAreaListener
该方法用于添加系统规避区变化事件的监听。通过监听 “avoidAreaChange” 参数,当系统规避区发生变化时,如软键盘弹出或收起、设备旋转等,会触发相应的回调函数,在回调中通过 runJavaScript() 的方法将变化的数据传递给 H5 页面。
async avoidAreaListener(): Promise<void> {
const windowClass = await this.webClassProxy.getMainWindow();
try {
windowClass.on('avoidAreaChange', (data) => {
this.webController.runJavaScript(`
window.dispatchEvent(new CustomEvent('statusBarChange',{ detail: ${JSON.stringify(data)} }));
`);
Logger.debug('Succeeded in enabling the listener for system avoid area changes. type:' +
JSON.stringify(data.type) + ', area: ' + JSON.stringify(data.area));
});
} catch (exception) {
Logger.error(`Failed to enable the listener for system avoid area changes. Cause code: ${exception.code}, message: ${exception.message}`);
}
}
registerJavaScriptProxy
注入 JavaScript 对象到 window 对象中,并在 window 对象中调用该对象的方法。实现 H5 页面调用原生方法。
Web({ src: CommonConstants.H5_URL, controller: this.webController })
.onControllerAttached(() => {
this.webController.registerJavaScriptProxy(this.webClassProxy, 'webClass',
['getAvoidArea', 'pxToVp', 'isFoldAndTablet', 'getWindowStatusType'],
[],
`{"javascriptProxyPermission":{"urlPermissionList":[{"scheme":"http","host":"${CommonConstants.HOST}","port":"${CommonConstants.PORT}","path":""}]}}`);
this.webController.refresh();
})
getAvoidArea
Plugins 类中的 getAvoidArea() 接口负责获取系统默认避让区域信息。此方法接收一个 AvoidAreaType 类型的参数,通过该参数可以获取当前应用窗口内容需要规避的区域。这些区域可能包括系统栏、刘海屏、手势操作区、软键盘等与窗口内容重叠时需要避让的区域。通过原生接口获取窗口实例,然后调用窗口的 getWindowAvoidArea 方法获取相应类型的避让区域,接口返回信息中包含对应避让区域是否可见、位置信息及宽高信息,并将结果返回给 H5 端。
async getAvoidArea(type: window.AvoidAreaType) {
const windowClass = await this.getMainWindow();
let avoidArea = windowClass.getWindowAvoidArea(type);
return avoidArea;
}
三、适配指导
3.1 安全区布局场景
图7 AvoidArea实现安全布局
RN适配指导
安全区布局场景主要是为了确保应用内容不会被系统状态栏、导航栏等遮挡。通过上述的 AvoidArea API 获取的避让区域相关信息,包括状态栏、导航栏以及挖孔区,给外层容器设置 padding,防止内部组件被避让区遮挡,从而实现安全布局效果。示例代码如下:
const FullScreenView = () => {
const [topPadding, setTopPadding] = useState(0);
const [bottomPadding, setBottomPadding] = useState(0);
const pixelRatio = PixelRatio.get() ? PixelRatio.get() : 1;
useEffect(() => {
const getAvoidArea = () => {
// 获取状态栏高度,设置上padding
let type = AvoidAreaType.TYPE_SYSTEM;
let avoidArea = Avoid.getWindowAvoidArea(type);
let topHeight = avoidArea.topRect.height / pixelRatio;
setTopPadding(topHeight);
// 获取导航栏高度,设置下padding
type = AvoidAreaType.TYPE_NAVIGATION_INDICATOR;
avoidArea = Avoid.getWindowAvoidArea(type);
let bottomHeight = avoidArea.bottomRect.height / pixelRatio;
setBottomPadding(bottomHeight);
};
getAvoidArea();
const listener = Avoid.addAvoidAreaListener(data => {
// 监听避让区域变化,逻辑处理
});
return () => {
Avoid.removeAvoidAreaListener();
};
}, []);
return (
<View style={[styles.container, { paddingTop: topPadding, paddingBottom: bottomPadding }]}>
<View style={styles.contentContainer}>
<Text style={[styles.textStyle, styles.otherTextStyle]}>title</Text>
<Text style={[styles.textStyle, styles.contentTextStyle]}>content</Text>
<Text style={[styles.textStyle, styles.otherTextStyle]}>footer</Text>
</View>
</View>
);
};
export default FullScreenView;
RN也提供了 SafeAreaView 安全布局组件,该组件可以自动将内容放置在安全区域内。在 HarmonyOS 上,这种方式存在底部导航栏没有自动避让的问题,因此建议使用上述的 AvoidArea API 方式实现安全区布局场景。
Flutter适配指导
安全区布局场景主要是为了确保应用内容不会被系统状态栏、导航栏等遮挡。Flutter 提供了 SafeArea 组件,该组件可以自动将内容放置在安全区域内。同时,也可以结合 AvoidAreaApi 获取的避让区域信息进行更精确的布局。
SafeArea(
child: Container(
// 这里可以放置应用的主要内容
child: Text('这是安全区布局内的内容'),
),
);
H5适配指导
该场景有两种实现方法:
-
webview 在安全区布局,H5 页面不需要做额外处理
-
webview 全屏布局,H5 获取状态栏、导航栏高度,设置 padding
(1)原生侧开启全屏布局
在 HarmonyOS 工程的 EntryAbility.ets 文件中的 onWindowStageCreate() 生命周期内,使用 setWindowLayoutFullScreen() 实现界面元素延伸到状态栏和导航区域;
示例代码如下:
windowObj: window.Window | undefined = undefined;
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.getMainWindow((err: BusinessError<void>, windowObj) => {
this.windowObj = windowObj;
// 设置全屏
windowObj.setWindowLayoutFullScreen(true);
})
}
(2)注入 JavaScript 对象
使用 registerJavaScriptProxy() 接口将原生侧方法注入到 H5 页面中,H5 页面可以调用原生方法获取状态栏和导航区域高度。
Web({ src: CommonConstants.H5_URL, controller: this.webController })
.onControllerAttached(() => {
this.webController.registerJavaScriptProxy(this.webClassProxy, 'webClass',
['getAvoidArea', 'pxToVp', 'isFoldAndTablet', 'getWindowStatusType'],
[],
`{"javascriptProxyPermission":{"urlPermissionList":[{"scheme":"http","host":"${CommonConstants.HOST}","port":"${CommonConstants.PORT}","path":""}]}}`);
this.webController.refresh();
})
(3)H5 页面示例代码
页面通过调用原生方法获取状态栏和导航条高度,并设置在外层容器中,实现状态栏和导航条的避让。
<template>
<div class="contain"
:style="{
paddingTop: `${paddingTop}px`,
paddingBottom: `${paddingBottom}px`
}">
<div class="header"></div>
<div class="body"></div>
<div class="footer"></div>
</div>
</template>
<script setup lang="ts">
import { onMounted, onBeforeUnmount } from 'vue';
const paddingTop = 0;
const paddingBottom = 0;
onMounted(() => {
if ((window as any).webClass) {
// 获取状态栏安全区高度
const paddingTop = await (window as any).webClass.getAvoidArea(AvoidAreaType.TYPE_SYSTEM).area.topRect.height;
// 获取导航条安全区高度
const paddingBottom = await (window as any).webClass.getAvoidArea(AvoidAreaType.TYPE_NAVIGATION_INDICATOR).area.bottomRect.height;
}
});
</script>
3.2 安全区布局+背景沉浸模式
图8 AvoidArea实现安全区布局+背景沉浸模式
RN适配指导
在安全区域布局的基础上,延伸绘制内容(如背景色、背景图)到状态栏和导航条区域,实现沉浸式效果。上述示例代码中 FullScreenView 已经实现了安全区布局,我们可以在这个组件的基础上延伸绘制内容。在 FullScreenView 的外层套一层 View 容器,用于设置背景,这样就可以实现背景沉浸模式。示例代码如下:
return (
<View style={styles.backgroundContainer}>
<FullScreenView/>
</View>
);
const styles = StyleSheet.create({
backgroundContainer: {
height: '100%',
width:'100%',
backgroundColor: 'gray',
}
})
Flutter适配指导
在背景沉浸模式下,需要使用 Stack 组件,背景全屏展示,然后使用 SafeArea 包裹安全区域。
Stack(
children: [
Image.asset(
'assets/background.png',
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
SafeArea(
child: Container(
child: Text('这是安全区布局内的内容'),
),
),
],
)
H5适配指导
在安全区域布局的基础上,延伸绘制内容(如背景色、背景图)到状态栏和导航条区域,实现沉浸式效果。实现方式与安全区布局相似,将 webview 设置全屏沉浸式,H5 背景全屏、内容设置 padding。
- 原生侧开启全屏布局
在工程的 EntryAbility.ets 文件中的 onWindowStageCreate() 生命周期内,使用 setWindowLayoutFullScreen() 实现界面元素延伸到状态栏和导航区域。
示例代码如下:
windowObj: window.Window | undefined = undefined;
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.getMainWindow((err: BusinessError<void>, windowObj) => {
this.windowObj = windowObj;
// 设置全屏
windowObj.setWindowLayoutFullScreen(true);
})
}
- 注入 JavaScript 对象
使用 registerJavaScriptProxy() 接口将原生侧方法注入到 H5 页面中,H5 页面可以调用原生方法获取状态栏和导航区域高度。
Web({ src: CommonConstants.H5_URL, controller: this.webController })
.onControllerAttached(() => {
this.webController.registerJavaScriptProxy(this.webClassProxy, 'webClass',
['getAvoidArea', 'pxToVp', 'isFoldAndTablet', 'getWindowStatusType'],
[],
`{"javascriptProxyPermission":{"urlPermissionList":[{"scheme":"http","host":"${CommonConstants.HOST}","port":"${CommonConstants.PORT}","path":""}]}}`);
this.webController.refresh();
})
- H5 页面示例代码
页面通过调用原生方法获取状态栏和导航条高度,并设置在外层容器中,实现状态栏和导航条的避让。
<template>
<div class="contain">
<div class="header"
:style="{
paddingTop: `${paddingTop}px`
}">
</div>
<div class="body"></div>
<div class="footer"
:style="{
paddingBottom: `${paddingBottom}px`
}">
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
const paddingTop = 0;
const paddingBottom = 0;
onMounted(() => {
if ((window as any).webClass) {
// 获取状态栏安全区高度
const paddingTop = await (window as any).webClass.getAvoidArea(AvoidAreaType.TYPE_SYSTEM).area.topRect.height;
// 获取导航条安全区高度
const paddingBottom = await (window as any).webClass.getAvoidArea(AvoidAreaType.TYPE_NAVIGATION_INDICATOR).area.bottomRect.height;
}
});
</script>
3.3 全屏布局+避让场景
图9 AvoidArea实现全屏布局+避让场景
RN适配指导
- 原生侧开启全屏布局
在 HarmonyOS 工程的 EntryAbility.ets 文件中的 onWindowStageCreate() 生命周期内:
1、setWindowLayoutFullScreen() 实现界面元素延伸到状态栏和导航区域; 2、再通过 setWindowSystemBarEnable() 将主窗口状态栏和底部导航条隐藏,实现页面的全屏布局。
示例代码如下:
async onWindowStageCreate(windowStage: WindowStage) {
windowStage.getMainWindow((err: BusinessError, data) => {
let windowClass: Window | undefined = undefined;
windowClass = data;
// 开启全屏
let orientation = window.Orientation.AUTO_ROTATION_RESTRICTED;
windowClass.setPreferredOrientation(orientation);
// 隐藏状态栏、导航条
let names: Array<'status' | 'navigation'> = [];
windowClass.setWindowSystemBarEnable(names)
})
}
- 避让刘海屏/挖孔区
在 RN 工程中通过 AvoidArea API 的接口 getWindowAvoidArea() 获取挖孔区避让数据,计算并调整子元素的位置,规避挖孔区。示例代码如下:
let type = AvoidAreaType.TYPE_CUTOUT;
//获取刘海屏/挖孔区位置信息
let avoidArea = Avoid.getWindowAvoidArea(type);
//...获取避让区信息后计算并调整子元素的位置,规避挖孔区
Flutter适配指导
在全屏布局中,需要隐藏系统状态栏和导航栏,并添加避让区域变化监听。根据避让区域的变化动态调整布局,确保应用在各种情况下都能正常显示。
- 隐藏状态栏和导航栏
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays:[]);
- 添加避让区域变化监听,根据避让区域的变化动态调整布局
/// samples/avoid_area_sample/lib/game_page.dart
AvoidAreaApi.addAvoidAreaListener(event => {
var result = json.decode(event);
AvoidArea avoidArea = AvoidArea.fromJson(result["area"]);
switch(AvoidAreaType.values[result["type"]]){
// 状态栏
case AvoidAreaType.system:
avoidAreaSystem = avoidArea;
break;
// 刘海区域
case AvoidAreaType.cutout:
avoidAreaCutout = avoidArea;
break;
// 键盘区域
case AvoidAreaType.keyboard:
avoidAreaKeyboard = avoidArea;
break;
// 手势区域
case AvoidAreaType.systemGesture:
avoidAreaSystemGesture = avoidArea;
break;
// 底部导航栏
case AvoidAreaType.navigationIndicator:
avoidAreaNavigationIndicator = avoidArea;
break;
}
update();
});
H5适配指导
在全屏布局中,需要隐藏系统状态栏和导航栏,并添加避让区域变化监听。根据避让区域的变化动态调整布局,确保应用在各种情况下都能正常显示。
- 原生侧开启全屏布局
在 HarmonyOS 工程的 EntryAbility.ets 文件中的 onWindowStageCreate() 生命周期内:
1、setWindowLayoutFullScreen() 接口实现界面元素延伸到状态栏和导航区域; 2、再通过 setWindowSystemBarEnable() 接口将主窗口状态栏和底部导航条隐藏,实现页面的全屏布局。
示例代码如下:
windowObj: window.Window | undefined = undefined;
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.getMainWindow((err: BusinessError<void>, windowObj) => {
this.windowObj = windowObj;
// 隐藏状态栏、导航条
windowObj.setSpecificSystemBarEnabled('status', false);
windowObj.setSpecificSystemBarEnabled('navigationIndicator', false);
// 设置全屏
windowObj.setWindowLayoutFullScreen(true);
})
}
- 注入 JavaScript 对象
使用 registerJavaScriptProxy() 接口将原生侧方法注入到 H5 页面中,H5 页面可以调用原生方法获取状态栏和导航区域高度。
Web({ src: CommonConstants.H5_URL, controller: this.webController })
.onControllerAttached(() => {
this.webController.registerJavaScriptProxy(this.webClassProxy, 'webClass',
['getAvoidArea', 'pxToVp', 'isFoldAndTablet', 'getWindowStatusType'],
[],
`{"javascriptProxyPermission":{"urlPermissionList":[{"scheme":"http","host":"${CommonConstants.HOST}","port":"${CommonConstants.PORT}","path":""}]}}`);
this.webController.refresh();
})
- 在 H5 页面中计算刘海屏/挖孔区位置
页面通过调用原生方法获取刘海屏区域位置,通过计算转换成相对位置和避让的数值。
static async getAvoidAreaLocation(): Promise<AreaAndMargin> {
let location = AreaLocation.none;
if ((window as any).webClass) {
const avoidArea = await (window as any).webClass.getAvoidArea();
//根据取避让区信息计算并调整子元素的位置,并返回AreaLocation和距离,下面是避让区域处于顶部的情况
if (this.cameraIsHere(avoidArea.topRect)) {
const left = AreaUtils.px2vp(avoidArea.topRect.left);
const right = AreaUtils.px2vp(avoidArea.topRect.left + avoidArea.topRect.width);
const center = window.screen.width / 2;
let marginValue = left;
if (left <= center && center <= right) {
location = AreaLocation.topCenter;
} else if (center < left) {
location = AreaLocation.rightTop;
marginValue = window.screen.width - AreaUtils.px2vp(avoidArea.topRect.left);
} else {
location = AreaLocation.leftTop;
}
return { areaLocation: location, marginValue: marginValue };
}
//底部以及左右两边的情况也相应做处理
......
}
return { areaLocation: location, marginValue: 0 };
}
- H5 页面示例代码
页面通过调用原生方法获取避让区域,并监听避让区域变化事件,根据回调设定不同区域的样式,实现避让。
<template>
<div class="contain">
<div class="header"
:style="{
marginTop: `${topMargin}px`
}">
</div>
<div class="body"></div>
<div class="footer"
:style="{
marginBottom: `${bottomMargin}px`
}">
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
import { AreaUtils } from '../utils/AreaUtils';
更多关于HarmonyOS 鸿蒙Next区域避让开发指导的实战教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙Next的区域避让开发主要使用ArkTS/TypeScript实现。核心API是AreaAvoidance
模块,提供registerAvoidanceArea
方法注册避让区域,参数包括区域范围(矩形坐标)和避让优先级。系统会自动调整布局避免遮挡注册区域。
关键开发步骤:
- 导入模块:
import areaAvoidance from '@ohos.areaAvoidance'
- 定义避让区域:
let area = { left:0, top:0, width:100, height:200 }
- 注册区域:
areaAvoidance.registerAvoidanceArea(area, areaAvoidance.Priority.HIGH)
系统会根据优先级动态调整其他组件位置。可通过unregisterAvoidanceArea
取消注册。