HarmonyOS 互动卡片实战进阶:配置详解与双触发机制全链路实践
前言
在上一篇文章中,我们系统介绍了互动卡片的概念原理、双态架构和基础 API。但概念终要落地——form_config.json中的sceneAnimationParams如何配置?module.json5中如何声明LiveFormExtensionAbility?点击触发和摇一摇触发两条路径的区别是什么?requestOverflow破框区域如何计算?
本文将从配置文件详解、双 Ability 声明、两种触发机制到破框区域计算,逐一拆解互动卡片的配置与触发全链路。
一、form_config.json 配置详解
1.1 完整配置结构
form_config.json是互动卡片的核心配置文件,定义了卡片的基本信息、尺寸、触发方式等:
{"forms":[{"name":"DeliveryCard","displayName":"$string:DeliveryCard","description":"$string:DeliveryCardDes","src":"./ets/widget/pages/DeliveryCard.ets","uiSyntax":"arkts","isDynamic":true,"defaultDimension":"2*2","supportDimensions":["2*2"],"sceneAnimationParams":{"abilityName":"DeliveryLiveCardAbility","triggerTypes":["click","shake"]}}]}1.2 关键字段说明
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
name | 是 | string | 卡片名称,卡片五元组之一 |
displayName | 是 | string | 卡片显示名称 |
description | 是 | string | 卡片描述 |
src | 是 | string | 卡片 UI 页面路径 |
uiSyntax | 是 | string | UI 语法,固定为"arkts" |
isDynamic | 是 | boolean | 是否为动态卡片,互动卡片必须为true |
defaultDimension | 是 | string | 默认尺寸 |
supportDimensions | 是 | string[] | 支持的尺寸列表 |
sceneAnimationParams | 否 | object | 场景动效配置(互动卡片关键字段) |
1.3 sceneAnimationParams 详解
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
abilityName | 是 | string | 激活时启动的LiveFormExtensionAbility名称 |
triggerTypes | 否 | string[] | 触发动画方式,支持"click"和"shake" |
重要提示:
sceneAnimationParams.abilityName必须和module.json5里LiveFormExtensionAbility的name一字不差,否则触发时系统找不到目标。
1.4 四种卡片的配置差异
| 卡片 | triggerTypes | 说明 |
|---|---|---|
| 睡眠卡片 | ["click"] | 仅点击触发 |
| 快递卡片 | ["click", "shake"] | 点击 + 摇一摇 |
| 运动卡片 | ["click"] | 仅点击触发 |
| 音乐卡片 | ["click"] | 仅点击触发 |
二、module.json5 双 Ability 声明
2.1 完整配置
{ "module": { "name": "entry", "type": "entry", "mainElement": "EntryAbility", "deviceTypes": ["phone", "tablet"], "pages": "$profile:main_pages", "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets" } ], "extensionAbilities": [ { "name": "EntryFormAbility", "srcEntry": "./ets/entryformability/EntryFormAbility.ets", "type": "form", "metadata": [ { "name": "ohos.extension.form", "resource": "$profile:form_config" } ] }, { "name": "DeliveryLiveCardAbility", "srcEntry": "./ets/livecardability/DeliveryLiveCardAbility.ets", "type": "liveForm" } ] } }2.2 双 Ability 对比
| 维度 | FormExtensionAbility | LiveFormExtensionAbility |
|---|---|---|
type | "form" | "liveForm" |
| 管理状态 | 非激活态 | 激活态 |
| 生命周期 | onCreate→onUpdateForm→onDestroy | onLiveFormCreate→onLiveFormDestroy |
| 渲染能力 | 静态卡片 UI | 动态动画 UI |
| 传感器 | 不支持 | 支持陀螺仪等 |
2.3 配置注意事项
- abilityName 必须一致:
form_config.json中sceneAnimationParams.abilityName的字符串必须与module.json5中extensionAbilities的name字段完全一致 - type 必须正确:
FormExtensionAbility的type是"form",LiveFormExtensionAbility的type是"liveForm" - metadata 必须配置:
FormExtensionAbility需要metadata指向form_config.json
三、点击触发机制详解
3.1 点击触发流程
点击触发是互动卡片最常用的激活方式,完整流程如下:
用户点击卡片 ↓ 卡片 UI 调用 postCardAction(MESSAGE) 发送 "requestOverflow" 消息 ↓ FormExtensionAbility.onFormEvent 接收消息 ↓ 解析消息参数(widthRatio、heightRatio、duration) ↓ 调用 formProvider.getFormRect 获取卡片位置尺寸 ↓ 计算破框区域(area) ↓ 调用 formProvider.requestOverflow 向系统申请破框 ↓ 系统创建 LiveFormExtensionAbility 实例 ↓ onLiveFormCreate → session.loadContent 加载动画 UI3.2 点击触发完整代码
// 1. 卡片 UI 中发送消息// entry/src/main/ets/widget/pages/DeliveryCard.ets@Entry@Componentstruct DeliveryCard{build(){RelativeContainer(){// 卡片内容...}.width('100%').height('100%').onClick(()=>{// 关键:点击时发送 requestOverflow 消息ActionUtils.requestOverFlow(this,LiveCardScale.DELIVERY_WIDTH,// 宽度比例LiveCardScale.DELIVERY_HEIGHT,// 高度比例LIVE_CARD_DURATION// 动画时长);});}}// 2. ActionUtils.requestOverFlow 实现// entry/src/main/ets/utils/ActionUtils.etsexportclassActionUtils{staticrequestOverFlow(component:object,widthRatio:number,heightRatio:number,duration:number):void{constparams:Record<string,Object>={message:'requestOverflow',widthRatio:widthRatio,heightRatio:heightRatio,duration:duration};postCardAction(component,{action:'message',message:JSON.stringify(params)});}staticjumpAppPage(component:object,pageName:string):void{postCardAction(component,{action:'router',abilityName:'EntryAbility',params:{targetPage:pageName}});}}// 3. FormExtensionAbility 处理消息// entry/src/main/ets/entryformability/EntryFormAbility.etsasynconFormEvent(formId:string,message:string):Promise<void>{constparams:Record<string,Object>=JSON.parse(message);constshortMessage:string=params.messageasstring;if(shortMessage==='requestOverflow'){constwidthRatio=params.widthRatioasnumber;constheightRatio=params.heightRatioasnumber;constduration=params.durationasnumber;awaitthis.requestOverflow(formId,widthRatio,heightRatio,duration);}}privateasyncrequestOverflow(formId:string,widthRatio:number,heightRatio:number,duration:number):Promise<void>{try{constformRect=awaitformProvider.getFormRect(formId);constcardWidth=formRect.width*widthRatio;constcardHeight=formRect.height*heightRatio;constleftOffset=(formRect.width-cardWidth)/2;consttopOffset=(formRect.height-cardHeight)/2;awaitformProvider.requestOverflow(formId,{area:{left:leftOffset,top:topOffset,width:cardWidth,height:cardHeight},duration:duration});}catch(err){console.error(`requestOverflow error:${JSON.stringify(err)}`);}}四、摇一摇触发机制详解
4.1 摇一摇触发流程
摇一摇触发是 HarmonyOS 7.0 新增的激活方式,流程如下:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 用户摇动设备 | 系统识别摇一摇事件 |
| 2 | 查找triggerTypes含"shake"的卡片 | 匹配支持的卡片 |
| 3 | 读取sceneAnimationParams.abilityName | 获取 LiveFormExtensionAbility 名称 |
| 4 | 触发FormExtensionAbility.onUpdateForm | 系统将摇一摇事件发送给卡片 |
| 5 | 调用requestOverflow请求激活 | FormExtensionAbility 中主动拉起 |
| 6 | 创建LiveFormExtensionAbility实例 | 系统自动创建 |
| 7 | 调用onLiveFormCreate方法 | 加载动画 UI |
4.2 摇一摇触发配置
{"sceneAnimationParams":{"abilityName":"DeliveryLiveCardAbility","triggerTypes":["click","shake"]}}注意:摇一摇激活互动卡片能力仅在 HarmonyOS 7.0 以上版本触发。7.0 以下系统不识别
"shake",配置了也不生效。
4.3 摇一摇触发实现
// 在 FormExtensionAbility.onUpdateForm 中处理摇一摇事件asynconUpdateForm(formId:string):Promise<void>{// 摇一摇触发时,系统自动调用此方法// 在此处调用 requestOverflow 激活互动卡片console.info(`摇一摇触发,激活卡片:${formId}`);awaitthis.requestOverflow(formId,1.0,1.0,5000);}五、破框区域计算
5.1 破框原理
破框(Overflow)是互动卡片的核心特性,允许激活态的渲染区域超出原始卡片边界。破框区域通过requestOverflow的area参数指定:
interfaceOverflowInfo{area:{left:number;// 破框区域左上角 X 坐标(相对卡片)top:number;// 破框区域左上角 Y 坐标(相对卡片)width:number;// 破框区域宽度height:number;// 破框区域高度};duration:number;// 动画时长(毫秒)}5.2 破框区域计算
/** * 计算破框区域 * @param formRect 卡片原始位置和尺寸 * @param expandRatio 扩展比例(> 1.0 表示破框放大) * @returns 破框区域信息 */functioncalculateOverflowArea(formRect:formInfo.Rect,expandRatio:number):{left:number;top:number;width:number;height:number}{// 计算破框后的尺寸constexpandedWidth=formRect.width*expandRatio;constexpandedHeight=formRect.height*expandRatio;// 居中偏移(破框区域中心与卡片中心对齐)constleftOffset=(formRect.width-expandedWidth)/2;consttopOffset=(formRect.height-expandedHeight)/2;return{left:leftOffset,top:topOffset,width:expandedWidth,height:expandedHeight};}5.3 不同卡片的破框参数
| 卡片 | 宽度比例 | 高度比例 | 动画时长 | 说明 |
|---|---|---|---|---|
| 睡眠卡片 | 1.5 | 1.5 | 5000ms | 气球飘出边界,需要较大扩展空间 |
| 快递卡片 | 1.3 | 1.3 | 5000ms | 憨憨跑动路线,中等扩展 |
| 运动卡片 | 1.4 | 1.4 | 5000ms | 庆祝动画,需要较大空间 |
| 音乐卡片 | 1.2 | 1.2 | 4000ms | 专辑飞出,较小扩展 |
六、常见配置错误与排查
6.1 常见配置错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
| 激活无响应 | abilityName拼写不一致 | 确保form_config.json和module.json5中名称完全一致 |
| 摇一摇不触发 | 系统版本 < 7.0 | 升级到 HarmonyOS 7.0+ |
| 破框区域不对 | 计算错误 | 检查getFormRect返回值,确保居中计算正确 |
| 动画白屏 | loadContent路径错误 | 检查livecardability/pages/路径是否正确 |
| 卡片类型错误 | isDynamic未设置为true | 动态卡片必须设置isDynamic: true |
6.2 配置检查清单
/** * 互动卡片配置检查清单 */exportclassLiveFormConfigChecker{staticcheckConfig(formConfig:object,moduleConfig:object):CheckResult{consterrors:string[]=[];constwarnings:string[]=[];// 1. 检查 isDynamicif(!formConfig['isDynamic']){errors.push('isDynamic 必须为 true');}// 2. 检查 sceneAnimationParamsconstsceneParams=formConfig['sceneAnimationParams'];if(!sceneParams||!sceneParams['abilityName']){errors.push('sceneAnimationParams.abilityName 未配置');}// 3. 检查 module.json5 中的 LiveFormExtensionAbilityconstextAbilities=moduleConfig['extensionAbilities']||[];constliveFormAbility=extAbilities.find((a:Record<string,string>)=>a['type']==='liveForm');if(!liveFormAbility){errors.push('module.json5 中未声明 type 为 liveForm 的 extensionAbility');}// 4. 检查 abilityName 一致性if(sceneParams&&liveFormAbility){if(sceneParams['abilityName']!==liveFormAbility['name']){errors.push(`abilityName 不一致: form_config=${sceneParams['abilityName']},`+`module=${liveFormAbility['name']}`);}}// 5. 检查摇一摇版本consttriggerTypes=sceneParams?.['triggerTypes']||[];if(triggerTypes.includes('shake')){warnings.push('摇一摇触发需要 HarmonyOS 7.0+');}return{isValid:errors.length===0,errors:errors,warnings:warnings};}}interfaceCheckResult{isValid:boolean;errors:string[];warnings:string[];}七、总结
本文从配置与触发角度深入讲解了互动卡片的实战要点:
- form_config.json 配置:
sceneAnimationParams的abilityName和triggerTypes是关键,isDynamic必须为true - module.json5 声明:
FormExtensionAbility(type:"form")和LiveFormExtensionAbility(type:"liveForm")双 Ability 必须同时声明 - 点击触发:卡片 →
postCardAction(MESSAGE)→FormExtensionAbility.onFormEvent→requestOverflow - 摇一摇触发:系统检测 shake →
FormExtensionAbility.onUpdateForm→requestOverflow(需 HarmonyOS 7.0+) - 破框区域计算:通过
getFormRect获取卡片尺寸,计算居中偏移,指定area和duration
下一篇将深入讲解三方通信架构与数据传递,包括动态卡片、应用、互动卡片之间的跨进程通信,点击阅读通信篇 →
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- 互动卡片开发实践文档:华为开发者文档
- 卡片配置文件说明:华为开发者文档
- 互动卡片示例代码:GitCode
- 开源鸿蒙跨平台社区:CSDN 社区