HarmonyOS 互动卡片实战进阶:配置详解与双触发机制全链路实践
·
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 加载动画 UI
3.2 点击触发完整代码
// 1. 卡片 UI 中发送消息
// entry/src/main/ets/widget/pages/DeliveryCard.ets
@Entry
@Component
struct 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.ets
export class ActionUtils {
static requestOverFlow(
component: object,
widthRatio: number,
heightRatio: number,
duration: number
): void {
const params: Record<string, Object> = {
message: 'requestOverflow',
widthRatio: widthRatio,
heightRatio: heightRatio,
duration: duration
};
postCardAction(component, {
action: 'message',
message: JSON.stringify(params)
});
}
static jumpAppPage(component: object, pageName: string): void {
postCardAction(component, {
action: 'router',
abilityName: 'EntryAbility',
params: { targetPage: pageName }
});
}
}
// 3. FormExtensionAbility 处理消息
// entry/src/main/ets/entryformability/EntryFormAbility.ets
async onFormEvent(formId: string, message: string): Promise<void> {
const params: Record<string, Object> = JSON.parse(message);
const shortMessage: string = params.message as string;
if (shortMessage === 'requestOverflow') {
const widthRatio = params.widthRatio as number;
const heightRatio = params.heightRatio as number;
const duration = params.duration as number;
await this.requestOverflow(formId, widthRatio, heightRatio, duration);
}
}
private async requestOverflow(
formId: string, widthRatio: number, heightRatio: number, duration: number
): Promise<void> {
try {
const formRect = await formProvider.getFormRect(formId);
const cardWidth = formRect.width * widthRatio;
const cardHeight = formRect.height * heightRatio;
const leftOffset = (formRect.width - cardWidth) / 2;
const topOffset = (formRect.height - cardHeight) / 2;
await formProvider.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 中处理摇一摇事件
async onUpdateForm(formId: string): Promise<void> {
// 摇一摇触发时,系统自动调用此方法
// 在此处调用 requestOverflow 激活互动卡片
console.info(`摇一摇触发,激活卡片: ${formId}`);
await this.requestOverflow(formId, 1.0, 1.0, 5000);
}
五、破框区域计算
5.1 破框原理
破框(Overflow)是互动卡片的核心特性,允许激活态的渲染区域超出原始卡片边界。破框区域通过 requestOverflow 的 area 参数指定:
interface OverflowInfo {
area: {
left: number; // 破框区域左上角 X 坐标(相对卡片)
top: number; // 破框区域左上角 Y 坐标(相对卡片)
width: number; // 破框区域宽度
height: number; // 破框区域高度
};
duration: number; // 动画时长(毫秒)
}
5.2 破框区域计算
/**
* 计算破框区域
* @param formRect 卡片原始位置和尺寸
* @param expandRatio 扩展比例(> 1.0 表示破框放大)
* @returns 破框区域信息
*/
function calculateOverflowArea(
formRect: formInfo.Rect,
expandRatio: number
): { left: number; top: number; width: number; height: number } {
// 计算破框后的尺寸
const expandedWidth = formRect.width * expandRatio;
const expandedHeight = formRect.height * expandRatio;
// 居中偏移(破框区域中心与卡片中心对齐)
const leftOffset = (formRect.width - expandedWidth) / 2;
const topOffset = (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 配置检查清单
/**
* 互动卡片配置检查清单
*/
export class LiveFormConfigChecker {
static checkConfig(formConfig: object, moduleConfig: object): CheckResult {
const errors: string[] = [];
const warnings: string[] = [];
// 1. 检查 isDynamic
if (!formConfig['isDynamic']) {
errors.push('isDynamic 必须为 true');
}
// 2. 检查 sceneAnimationParams
const sceneParams = formConfig['sceneAnimationParams'];
if (!sceneParams || !sceneParams['abilityName']) {
errors.push('sceneAnimationParams.abilityName 未配置');
}
// 3. 检查 module.json5 中的 LiveFormExtensionAbility
const extAbilities = moduleConfig['extensionAbilities'] || [];
const liveFormAbility = 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. 检查摇一摇版本
const triggerTypes = sceneParams?.['triggerTypes'] || [];
if (triggerTypes.includes('shake')) {
warnings.push('摇一摇触发需要 HarmonyOS 7.0+');
}
return {
isValid: errors.length === 0,
errors: errors,
warnings: warnings
};
}
}
interface CheckResult {
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
下一篇将深入讲解三方通信架构与数据传递,包括动态卡片、应用、互动卡片之间的跨进程通信,点击阅读通信篇 →
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐


所有评论(0)