HarmonyOS 鸿蒙Next功能交互挂件
HarmonyOS 鸿蒙Next功能交互挂件
一、场景概述
在移动应用开发中,不同设备的屏幕形态各异,如刘海屏、全面屏、折叠屏等,其UI差异较大,且各自存在避让区。为了确保不同设备下功能交互挂件UI位置以及尺寸展示的正确性,h5提供了一系列的适配和避让机制。本文将详细介绍功能交互挂件的实现原理以及适配指导。
1.1 使用场景
功能交互挂件的使用场景比较多,典型应用比如视频播放应用的暂停按钮、返回按钮等,这些挂件在不同设备以及设备的展示状态(横竖屏)下,显示的位置以及避让区域需要有所调整。本示例和设备无强相关的关系,因此下面给出根据断点分类的展示效果图。
| 横向断点 | sm | md | lg | xl |
|---|---|---|---|---|
| 展示逻辑 | 组件大小根据断点展示 | 组件大小根据断点展示 | 组件大小根据断点展示 | 组件大小根据断点展示 |
| 展示布局 | ![]() |
![]() |
![]() |
![]() |
1.2 常见问题
- 图文页左上角返回箭头紧贴顶部状态栏显示,导致部分点击无法选中
- 双屏、三屏态视频播放页播放按钮显示过大
- 三屏态连麦直播间按钮错位
1.3 多设备适配
- 适配点1:沉浸式切换(顶部状态栏的显隐)


- 适配点2:功能导航挂件尺寸多设备自适应适配
功能导航挂件尺寸支持在不同屏幕尺寸上自适应放大或缩小(如下图播放按钮、返回按钮)


- 适配点3:功能导航挂件软键盘适配
软键盘由底部呼出时,底部挂件横屏状态下可被软键盘遮挡;屏幕其他位置挂件进行自适应调整,避免被遮挡




二、开发指导
2.1 H5开发
2.1.1 关键能力
功能交互挂件的核心处理之一就是区域避让,这部分功能主要通过原生提供的能力进行实现,包含以下几个核心api。
avoidAreaListener(): 该方法主要用于避让区域事件的监听,通过监听"avoidAreaChange"事件,当状态栏、键盘等涉及避让区域的位置发生变化时,该事件就会被触发,执行对应的回调函数,之后将需要处理的数据通过**runJavaScript()**方法传递到h5页面。
async avoidAreaListener(): Promise<void> {
Logger.warn('Trying to add listener...')
const windowClass = await this.webClassProxy.getMainWindow();
try {
windowClass.off('avoidAreaChange')
windowClass.on('avoidAreaChange', (data) => {
this.webController.runJavaScript(`
window.dispatchEvent(new CustomEvent('statusBarChange',{ detail: ${JSON.stringify(data)} }));
`);
this.webController.runJavaScript(`
window.dispatchEvent(new CustomEvent('avoidAreaChange',{ detail: ${JSON.stringify(data)} }));
`);
Logger.warn('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}`);
}
}
通过Web组件的src属性引入H5页面,并使用**registerJavaScriptProxy()**原生侧方法,将JavaScript对象注入到window对象中,从而在window对象中调用该对象的方法,实现H5页面调用原生方法。
Web({ src: 'http://0.0.0.0', controller: this.webController })
.onControllerAttached(() => {
this.webController.registerJavaScriptProxy(this, 'webClass', ['pushToPage', 'clearPage', 'getLastPage']);
this.webController.refresh();
})
2.1.2 指导案例
以功能交互挂件为例,在vue开发框架下给出具体的开发指导。
说明: 功能交互挂件场景是以视频播放页面为例,页面进入默认沉浸式状态,变化主要围绕顶部状态栏的显示和挂件的UI位置、显示等。
- 沉浸式切换(控制顶部状态栏的显隐)
- 调用原生方法setFullScreen()进入沉浸式,监听当前组件挂载的父层容器的宽高,便于计算各挂件的展示位置。
const handleResize = () => {
containerHeight.value = document.getElementById('container')?.clientHeight;
};
onMounted(async () => {
await window.webClass.setWindowBackgroundColor('#000000');
await window.webClass.setWindowSystemBarProperties();
await window.webClass.setFullScreen();
await window.webClass.setWindowSystemBarEnable();
bottomMargin.value = avoidAreaStore.innerBottomMargin;
topMargin.value = avoidAreaStore.innerTopMargin;
containerHeight.value = document.getElementById('container')?.clientHeight || 0;
window.addEventListener('resize', handleResize);
})
- 调用setWindowSystemBarEnable()、disableWindowSystemBarEnable()方法控制顶部状态栏的显隐。
const toggle = async () => {
if(flag.value) {
await window.webClass.setWindowSystemBarEnable();
} else {
await window.webClass.disableWindowSystemBarEnable();
}
flag.value = !flag.value;
}
- 挂件尺寸多设备自适应
- 根据不同设备宽高,自定义设备断点store,用于判断当前窗口所处断点区间。
const DEFAULT_BREAKPOINT_SETTINGS: BreakpointSettings = {
xs: 0,
sm: 320,
md: 600,
lg: 840,
xl: 1440,
}
export const useBreakpointStore = defineStore('breakpoint', () => {
const curBreakpoint = ref<Breakpoints>();
const breakpointSettings = ref({...DEFAULT_BREAKPOINT_SETTINGS});
const windowWidth = ref(0);
const updateBreakpoint = () => {
windowWidth.value = window.innerWidth;
for (const [breakpointName, upperLimit] of Object.entries(breakpointSettings.value)) {
if (windowWidth.value >= upperLimit) {
curBreakpoint.value = breakpointName as Breakpoints;
}
}
}
updateBreakpoint();
window.addEventListener('resize', updateBreakpoint);
return {
curBreakpoint,
breakpointSettings,
windowWidth,
}
})
- 以播放按钮为例,使用断点控制不同设备下的大小。
const playButtonHeight = computed(() => {
switch (breakpointStore.curBreakpoint) {
case 'xs':
case 'sm':
return '50px';
case 'md':
return '60px';
case 'lg':
return '70px';
case 'xl':
return '80px';
default:
return '50px';
}
});
img.play {
height: v-bind(playButtonHeight);
aspect-ratio: 1;
position: absolute;
left: calc((100% - v-bind(playButtonHeight)) / 2);
}
- 软键盘弹出适配
- 页面横竖屏判断,便于控制全屏按钮是否展示。
const isLandScape = computed(() => {
return appStatusStore.appOrientation === 1 || appStatusStore.appOrientation === 3;
})
- 使用原生传入方法控制状态栏是否显示,用于区分功能交互挂件场景整体状态。
const toggle = async () => {
if(flag.value) {
await window.webClass.setWindowSystemBarEnable();
} else {
await window.webClass.disableWindowSystemBarEnable();
}
flag.value = !flag.value;
}
- 挂件区域避让、键盘避让
这里以输入栏底部避让为例(需要考虑的因素相对较多:竖屏下键盘弹起需避让输入栏,全屏按钮显示;横屏下键盘弹起需避让输入栏,全屏按钮不显示)。
const inputBottom = computed(() => {
return (isLandScape.value && avoidAreaStore.isShowKeyboard) ?
avoidAreaStore.keyboardHeight + 'px' : avoidAreaStore.isShowKeyboard?
40 + avoidAreaStore.keyboardHeight + 'px' : avoidAreaStore.innerBottomMargin === 0 ?
bottomMargin.value + 40 + 'px' : avoidAreaStore.innerBottomMargin + 40 + 'px';
})
2.1.3 示例代码
场景Sample示例代码地址:H5三方框架赋能指导配套代码
更多关于HarmonyOS 鸿蒙Next功能交互挂件的实战教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙Next的功能交互挂件是桌面组件,支持动态信息展示和快捷操作。用户可直接在桌面查看应用关键信息并执行常用功能,无需打开应用。挂件基于ArkTS开发,通过方舟编译器优化性能,实现高效渲染和低功耗运行。
这篇帖子详细介绍了在HarmonyOS Next环境下,针对H5页面中功能交互挂件(如视频播放按钮、返回按钮)的多设备适配方案,核心在于处理不同屏幕形态(刘海屏、折叠屏等)和状态(横竖屏、键盘弹出)下的布局避让与自适应。
帖子中提到的关键技术点非常准确:
- 避让区域监听:通过原生的
avoidAreaChange事件监听状态栏、键盘等系统避让区域的变化,并将变化数据实时同步到H5页面,这是实现动态避让的基础。 - 原生与H5通信:使用
registerJavaScriptProxy方法将原生能力注入到H5的window对象,使得H5能够直接调用如setWindowSystemBarEnable等原生方法,控制状态栏显隐,实现沉浸式切换。 - 响应式断点设计:在H5侧自定义断点(xs, sm, md, lg, xl),根据窗口宽度动态调整挂件尺寸(例如播放按钮在不同断点下设置不同高度),这是实现多设备自适应布局的关键策略。
- 综合布局计算:挂件的最终位置(如帖子中
inputBottom的计算)需要综合考量多个动态因素:横竖屏状态、键盘是否弹出及其高度、以及当前的系统避让区安全边距。这种计算逻辑确保了在各种复杂交互场景下UI元素的正确展示。
总体而言,该方案提供了一套完整的混合开发适配范式,即由原生侧提供动态环境信息与系统能力,由H5侧进行灵活的响应式UI计算与渲染,能有效解决帖子开头提到的挂件紧贴状态栏、尺寸过大、位置错位等常见问题。示例代码仓库为开发者提供了宝贵的参考实现。





