卡片独立进程包(FormStandaloneDemo)——库模块 HAR 承载卡片 UI 的完整方案

发布时间:2026/5/19 12:34:31

卡片独立进程包(FormStandaloneDemo)——库模块 HAR 承载卡片 UI 的完整方案 文章目录为什么需要独立卡片包项目结构第一步entry 模块配置——关联 library第二步library 模块配置——声明这是独立卡片包第三步卡片 UI 写在 library 里第四步FormAbility 逻辑还在 entry 里独立卡片包 vs 普通卡片方案对比卡片 form_config.json 里的 src 路径写法常见坑写在最后普通方案里卡片 UI 和应用代码放在同一个entry模块里。但如果你的卡片 UI 比较复杂或者想让多个应用复用同一套卡片 UIHarmonyOS 还有一种进阶方案把卡片 UI 单独放到一个shared库模块library里。这就是独立卡片包方案FormStandaloneDemo项目演示了这个用法。为什么需要独立卡片包传统方案的卡片 UI 代码混在entry模块里有几个问题卡片 UI 无法复用想在另一个应用里用相同的卡片 UI只能复制代码entry 模块体积膨胀卡片资源图片、动画全堆在 entry 里团队协作困难卡片 UI 和应用逻辑混在一个模块改一个可能影响另一个独立卡片包方案解决了这些问题卡片 UI 放在libraryshared 类型模块里entry通过配置关联它。项目结构FormStandaloneDemo/ ├── entry/ ← 应用主包 │ └── src/main/ │ ├── module.json5 ← 含 formWidgetModule: library │ └── ets/ │ ├── entryability/EntryAbility.ets │ └── entryformability/ │ └── EntryFormAbility.ets ← 卡片 Ability逻辑在这里 └── library/ ← 独立卡片包shared 模块 └── src/main/ ├── module.json5 ← 含 formExtensionModule: entry └── ets/ └── widget1/pages/ └── TransitionEffectExample1.ets ← 卡片 UI 页面第一步entry 模块配置——关联 libraryentry/src/main/module.json5新增formWidgetModule字段// entry/src/main/module.json5 { module: { name: entry, type: entry, extensionAbilities: [ { name: EntryFormAbility, srcEntry: ./ets/entryformability/EntryFormAbility.ets, label: $string:EntryFormAbility_label, description: $string:EntryFormAbility_desc, type: form, metadata: [ { name: ohos.extension.form, resource: $profile:form_config } ] } ], // 关键告诉系统卡片 UI 代码在 library 模块里 formWidgetModule: library } }第二步library 模块配置——声明这是独立卡片包library/src/main/module.json5// library/src/main/module.json5 { module: { name: library, type: shared, // 必须是 shared 类型 description: $string:shared_desc, deviceTypes: [default], deliveryWithInstall: true, // 关键告诉系统 FormExtensionAbility 在 entry 模块里 formExtensionModule: entry } }这两个字段是互相对应的entry.module.json5里formWidgetModule: library→ 说我的卡片 UI 在 library 里library.module.json5里formExtensionModule: entry→ 说我的 FormAbility 在 entry 里第三步卡片 UI 写在 library 里卡片 UI 的写法和普通卡片完全一样只是文件位置在library模块下// library/src/main/ets/widget1/pages/TransitionEffectExample1.ets// 这是一个带过渡动画效果的卡片示例EntryComponentstruct TransitionEffectExample1{Stateflag:booleantrue;Stateshow:stringshow;build(){Column(){// 控制图片显隐的按钮Button(this.show).width(80).height(30).margin(30).onClick((){if(this.flag){this.showhide;}else{this.showshow;}this.flag!this.flag;})if(this.flag){// 出现时从透明度0旋转180°变为正常状态过渡动画1000ms// 消失时从正常状态变为透明度0旋转180°过渡动画1000msImage($r(app.media.testImg)).width(200).height(200).transition(TransitionEffect.OPACITY.animation({duration:1000,curve:Curve.Ease}).combine(TransitionEffect.rotate({z:1,angle:180})))}}.width(100%)}}这个卡片展示了 HarmonyOS 的属性动画效果图片的出现和消失带有透明度渐变 Z 轴旋转动画。第四步FormAbility 逻辑还在 entry 里卡片 UI 在 library但 FormExtensionAbility 的代码仍然在 entry 里这是关键点// entry/src/main/ets/entryformability/EntryFormAbility.etsimport{formBindingData,FormExtensionAbility,formInfo}fromkit.FormKit;import{Want}fromkit.AbilityKit;exportdefaultclassEntryFormAbilityextendsFormExtensionAbility{// FormAbility 依然在 entry 模块onAddForm(want:Want):formBindingData.FormBindingData{constformData;returnformBindingData.createFormBindingData(formData);}onCastToNormalForm(formId:string):void{}onUpdateForm(formId:string):void{}onFormEvent(formId:string,message:string):void{}onRemoveForm(formId:string):void{}onAcquireFormState(want:Want):formInfo.FormState{returnformInfo.FormState.READY;}}独立卡片包 vs 普通卡片方案对比startuml title 普通方案 vs 独立卡片包方案 package 普通卡片方案 { rectangle entry 模块 { [EntryFormAbility.ets] [widget/pages/WidgetCard.ets] note right: 卡片 UI 和 Ability\n都在 entry 里 } } package 独立卡片包方案 { rectangle entry 模块 { [EntryFormAbility.ets] note right: formWidgetModule:\nlibrary } rectangle library 模块 (shared) { [widget1/pages/TransitionEffect.ets] note right: formExtensionModule:\nentry } [EntryFormAbility.ets] .. [widget1/pages/TransitionEffect.ets] : 关联 } enduml对比项普通方案独立卡片包方案卡片 UI 位置entry 模块library(shared) 模块可复用性不可复用可被多应用共享代码解耦UI 和逻辑混在一起UI 和逻辑分离配置复杂度简单需要两个 module.json5 互相关联适用场景小型应用卡片简单企业应用卡片 UI 需复用卡片 form_config.json 里的 src 路径写法独立卡片包里卡片配置的src路径写法略有不同// entry/src/main/resources/base/profile/form_config.json{forms:[{name:TransitionEffectExample1,// src 里包含 library 模块的路径src:bundle:com.samples.formstandalonedemo/library/ets/widget1/pages/TransitionEffectExample1,uiSyntax:arkts,window:{designWidth:720,autoDesignWidth:true},isDefault:true,updateEnabled:false,supportDimensions:[2*2],defaultDimension:2*2}]}关键是src的格式bundle:bundleName/moduleName/ets/路径/文件名不带 .ets 后缀。常见坑坑1library 的 type 必须是sharedlibrary 模块的module.json5里type必须填shared不能是library或其他值否则formExtensionModule字段不生效。坑2两个 module.json5 的互相关联不能缺entry里要有formWidgetModule: librarylibrary里要有formExtensionModule: entry少了任何一个系统都无法正确关联。坑3卡片 UI 里不能访问 entry 模块的资源library模块里的卡片 UI 代码只能用library自己的$r()资源不能引用 entry 模块的资源文件。如果需要共享资源要放在library/src/main/resources/里。写在最后独立卡片包方案是一个进阶用法对大多数应用来说不是必须的。但如果你在做企业级应用需要让多个模块复用同一套卡片 UI或者卡片 UI 本身非常复杂需要单独维护这个方案就很有价值了。理解formWidgetModule和formExtensionModule这两个配置字段的作用是使用这个方案的关键。

相关新闻