鸿蒙 ArkTS卡片编辑功能
ArkTS卡片编辑开发指南 本文介绍了ArkTS卡片的两级编辑页面实现方案。核心是通过FormEditExtensionAbility扩展能力,采用一级编辑页(Extension)和二级编辑页(UIAbility)的分层设计。开发步骤包括: 创建FormEditExtensionAbility并实现onSessionCreate回调 配置module.json5添加formEdit类型扩展能力 在
本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、卡片编辑
卡片编辑是ArkTS卡片提供的一种页面编辑能力,允许用户自定义卡片的内容和样式。卡片提供方可以实现自己的编辑页面,让用户按需配置卡片。
实现原理
卡片编辑采用两级编辑页的设计:
用户点击卡片编辑
↓
卡片使用方(桌面)检测到卡片支持编辑
↓
拉起卡片提供方的一级编辑页 (FormEditExtensionAbility)
↓
一级编辑页通过 startSecondPage 拉起二级编辑页
↓
用户在二级编辑页完成编辑操作
↓
编辑后的数据通过 updateForm 刷新卡片
核心组件
| 组件 | 作用 |
|---|---|
| FormEditExtensionAbility | 卡片编辑扩展能力,提供编辑页生命周期 |
| FormEditExtensionContext | 编辑上下文,提供startSecondPage方法 |
| UIExtensionContentSession | 管理UI扩展会话,用于加载页面 |
二、开发步骤
2.1 创建FormEditExtensionAbility
首先,在工程的entry模块中创建EntryFormEditAbility.ets文件,继承FormEditExtensionAbility。
// src/main/ets/entryformeditability/EntryFormEditAbility.ets
import { FormEditExtensionAbility } from '@kit.FormKit';
import { Want, UIExtensionContentSession } from '@kit.AbilityKit';
import { ExtensionEvent } from '../pages/model/ExtensionEvent';
const TAG: string = 'FormEditDemo[EntryFormEditAbility] -->';
export default class EntryFormEditAbility extends FormEditExtensionAbility {
// 创建时回调
onCreate() {
console.info(`${TAG} onCreate`);
}
// 切换到前台时回调
onForeground(): void {
console.info(`${TAG} onForeground.....`);
}
// 切换到后台时回调
onBackground(): void {
console.info(`${TAG} onBackground......`);
}
// 销毁时回调
onDestroy(): void {
console.info(`${TAG} onDestroy......`);
}
// 会话创建时回调(核心方法)
onSessionCreate(want: Want, session: UIExtensionContentSession) {
console.info(`${TAG} onSessionCreate start..... want: ${JSON.stringify(want)}`);
// 创建LocalStorage用于数据传递
let storage: LocalStorage = new LocalStorage();
// 创建ExtensionEvent对象,用于调用startSecondPage
let extensionEvent: ExtensionEvent = new ExtensionEvent();
extensionEvent.setStartSecondPage(() => this.startSecondPage());
storage.setOrCreate('extensionEvent', extensionEvent);
// 加载一级编辑页面
try {
session.loadContent('pages/Extension', storage);
} catch (e) {
console.error(`${TAG} EntryFormEditAbility loadContent err: ${JSON.stringify(e)}`);
}
}
// 会话销毁时回调
onSessionDestroy(session: UIExtensionContentSession) {
console.info(`${TAG} onSessionDestroy`);
}
// 拉起二级编辑页的方法
private startSecondPage(): void {
const bundleName: string = this.context.extensionAbilityInfo.bundleName;
const secPageAbilityName: string = 'FormEditSecPageAbility';
console.info(`${TAG} startSecondPage. bundleName: ${bundleName}, secPageAbilityName: ${secPageAbilityName}.`);
try {
// 调用startSecondPage拉起二级编辑页
this.context.startSecondPage({
bundleName: bundleName,
parameters: {
"secPageAbilityName": secPageAbilityName
}
});
} catch (err) {
console.error(`${TAG} startSecondPage failed: ${err}`);
}
}
}
2.2 创建ExtensionEvent工具类
ExtensionEvent类用于在一级编辑页中调用startSecondPage方法。
// src/main/ets/pages/model/ExtensionEvent.ets
const TAG: string = 'FormEditDemo[ExtensionEvent] -->';
export class ExtensionEvent {
private startSecondPage: () => void = () => {
console.info(`${TAG} startSecondPage is empty!`);
};
// 设置startSecondPage方法
public setStartSecondPage(startSecondPage: () => void) {
console.info(`${TAG} setStartSecondPage`);
this.startSecondPage = startSecondPage;
}
// 调用startSecondPage方法
public startFormEditSecondPage(): void {
console.info(`${TAG} startFormEditSecondPage`);
this.startSecondPage();
}
}
2.3 创建一级编辑页面
一级编辑页面是用户点击"编辑"后首先看到的页面。
// src/main/ets/pages/Extension.ets
import { UIExtensionContentSession } from '@kit.AbilityKit';
import { ExtensionEvent } from './model/ExtensionEvent';
let storage = new LocalStorage();
const TAG: string = 'FormEditDemo[Extension] -->';
@Entry(storage)
@Component
struct Extension {
@State message: string = 'UIExtension Provider';
private session: UIExtensionContentSession | undefined = storage.get<UIExtensionContentSession>('session');
private extensionEvent: ExtensionEvent | undefined = storage.get<ExtensionEvent>('extensionEvent');
onPageShow() {
console.info(`${TAG} onPageShow. extensionEvent: ${JSON.stringify(this.extensionEvent)}`);
}
build() {
Row() {
Column() {
// 标题
Text(this.message)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
// 添加按钮 - 点击后拉起二级编辑页
Button("添加")
.width('80%')
.type(ButtonType.Capsule)
.margin({ top: 20 })
.onClick(() => {
console.info(`${TAG} Button onClick`);
// 调用startFormEditSecondPage方法,触发startSecondPage
this.extensionEvent?.startFormEditSecondPage();
})
}
}
.justifyContent(FlexAlign.Center)
.width('100%')
}
}
2.4 创建二级编辑页面
二级编辑页面是实际进行编辑操作的页面。这里需要创建对应的UIAbility。
// src/main/ets/formeditssecpageability/FormEditSecPageAbility.ets
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = 'FormEditSecPageAbility';
const DOMAIN_NUMBER: number = 0xFF00;
export default class FormEditSecPageAbility extends UIAbility {
onCreate(want, launchParam) {
hilog.info(DOMAIN_NUMBER, TAG, 'Ability onCreate');
// 获取从一级编辑页传递的参数
if (want?.parameters) {
let params = want.parameters;
hilog.info(DOMAIN_NUMBER, TAG, `收到参数: ${JSON.stringify(params)}`);
}
}
onWindowStageCreate(windowStage: window.WindowStage) {
hilog.info(DOMAIN_NUMBER, TAG, 'onWindowStageCreate');
// 加载二级编辑页面
windowStage.loadContent('pages/EditSecondPage', (err, data) => {
if (err) {
hilog.error(DOMAIN_NUMBER, TAG, `加载页面失败: ${JSON.stringify(err)}`);
return;
}
hilog.info(DOMAIN_NUMBER, TAG, '页面加载成功');
});
}
}
// src/main/ets/pages/EditSecondPage.ets
@Entry
@Component
struct EditSecondPage {
@State selectedCity: string = '北京';
@State selectedUnit: string = '摄氏度';
build() {
Column() {
// 标题
Text('编辑天气卡片')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
// 城市选择
Row() {
Text('选择城市:')
.fontSize(16)
.width(100)
Picker({ selected: this.selectedCity })
.onChange((value: string) => {
this.selectedCity = value;
})
}
.margin(10)
// 单位选择
Row() {
Text('温度单位:')
.fontSize(16)
.width(100)
Radio({ value: '摄氏度', group: 'unit' })
.checked(this.selectedUnit === '摄氏度')
.onChange(() => {
this.selectedUnit = '摄氏度';
})
Text('摄氏度')
.margin({ right: 20 })
Radio({ value: '华氏度', group: 'unit' })
.checked(this.selectedUnit === '华氏度')
.onChange(() => {
this.selectedUnit = '华氏度';
})
Text('华氏度')
}
.margin(10)
// 保存按钮
Button('保存')
.width('80%')
.type(ButtonType.Capsule)
.margin({ top: 30 })
.onClick(() => {
console.info(`保存设置: 城市=${this.selectedCity}, 单位=${this.selectedUnit}`);
// 这里调用updateForm刷新卡片
this.saveAndRefresh();
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Start)
.padding(20)
}
saveAndRefresh() {
// 构建新数据
let formData = {
'city': this.selectedCity,
'unit': this.selectedUnit,
'updateTime': new Date().toLocaleString()
};
// TODO: 调用updateForm刷新卡片
console.info('刷新卡片数据:', JSON.stringify(formData));
// 返回上一页
router.back();
}
}
2.5 配置module.json5
在module.json5中添加卡片编辑扩展能力的配置。
// src/main/module.json5
{
"module": {
// ... 其他配置
"extensionAbilities": [
// 已有的FormExtensionAbility
{
"name": "EntryFormAbility",
"srcEntry": "./ets/entryformability/EntryFormAbility.ets",
"type": "form"
},
// 新增的FormEditExtensionAbility
{
"name": "EntryFormEditAbility",
"srcEntry": "./ets/entryformeditability/EntryFormEditAbility.ets",
"type": "formEdit"
}
],
"abilities": [
// 二级编辑页的UIAbility
{
"name": "FormEditSecPageAbility",
"srcEntry": "./ets/formeditssecpageability/FormEditSecPageAbility.ets",
"description": "$string:FormEditSecPageAbility_desc",
"icon": "$media:icon",
"label": "$string:FormEditSecPageAbility_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background"
}
]
}
}
2.6 配置卡片form_config.json
在卡片的配置文件中添加formConfigAbility字段,指向卡片编辑扩展能力。
// resources/base/profile/form_config.json
{
"forms": [
{
"name": "widget",
"displayName": "$string:widget_display_name",
"description": "$string:widget_desc",
"src": "./ets/widget/pages/WidgetCard.ets",
"uiSyntax": "arkts",
// 关键:指定卡片编辑扩展能力
"formConfigAbility": "ability://EntryFormEditAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"isDynamic": true,
"isDefault": true,
"updateEnabled": false,
"defaultDimension": "2×2",
"supportDimensions": [
"2×2",
"2×4",
"4×4"
]
}
]
}
2.7 配置页面路由
在main_pages.json中注册Extension页面。
// resources/base/profile/main_pages.json
{
"src": [
"pages/Index",
"pages/Extension", // 一级编辑页
"pages/EditSecondPage" // 二级编辑页
]
}
三、流程时序图
用户 桌面 FormEditExtensionAbility 二级编辑页
| | | |
| 点击卡片编辑 | | |
|---------------------->| | |
| | 检测到formConfigAbility配置 | |
| |--------------------------------->| |
| | | onSessionCreate |
| | | | |
| | | 加载一级编辑页 |
| | |----> |
| | | Extension.ets |
| | | |
| | | 用户点击"添加"按钮 |
| | |<---- |
| | | |
| | | startSecondPage() |
| | |----|-------------------->|
| | | | 拉起二级编辑页 |
| | | | |
| | | | FormEditSecPageAbility
| | | | |
| | | | 用户完成编辑 |
| | | |<-------------------|
| | | | |
| | | | updateForm刷新卡片 |
| | | |----> |
| | | | |
| 卡片更新显示 | | | |
|<----------------------|----------------------------------|----| |
四、说明
4.1 核心配置
| 配置项 | 位置 | 说明 |
|---|---|---|
| extensionAbilities | module.json5 | 添加type为"formEdit"的扩展能力 |
| formConfigAbility | form_config.json | 指定卡片编辑扩展能力,格式为"ability://名称" |
4.2 核心方法
| 方法 | 所属类 | 作用 |
|---|---|---|
| onSessionCreate | FormEditExtensionAbility | 会话创建时回调,加载一级编辑页 |
| startSecondPage | FormEditExtensionContext | 拉起二级编辑页 |
| loadContent | UIExtensionContentSession | 加载一级编辑页面 |
4.3 数据传递
// 通过LocalStorage传递数据
let storage: LocalStorage = new LocalStorage();
storage.setOrCreate('extensionEvent', extensionEvent);
session.loadContent('pages/Extension', storage);
// 通过startSecondPage的parameters传递参数
this.context.startSecondPage({
bundleName: bundleName,
parameters: {
"secPageAbilityName": secPageAbilityName,
"formId": formId,
"config": JSON.stringify(configData)
}
});
五、注意事项
5.1 版本要求
| 特性 | 最低API版本 |
|---|---|
| FormEditExtensionAbility | API 18+ |
5.2 限制
| 限制项 | 说明 |
|---|---|
| formConfigAbility格式 | 必须为"ability://扩展能力名称" |
| 二级编辑页类型 | 必须是UIAbility,不能是Extension |
| 数据持久化 | 编辑后的数据需要通过updateForm刷新卡片 |
总结
ArkTS卡片编辑的核心:
-
两级编辑页设计:
-
一级编辑页:FormEditExtensionAbility
-
二级编辑页:普通UIAbility
-
-
核心流程:
-
配置
formConfigAbility -
实现
FormEditExtensionAbility -
onSessionCreate中加载一级编辑页 -
一级编辑页调用
startSecondPage拉起二级编辑页 -
二级编辑页完成编辑后
updateForm刷新卡片
-
-
关键配置:
-
module.json5中添加type为"formEdit"的扩展能力
-
form_config.json中添加formConfigAbility字段
-
更多推荐



所有评论(0)