Harmony OS 卡片能力
注意:
- 把 卡片 分成两种
- 静态卡片: 不允许其他事件的触发( 只能进行整体事件触发 ), 并且需要使用 FormLink 组件包裹
- 动态卡片: 可以触发其他事件, 但是不能使用 FromLink 来触发拉起 Ability
- 如何设置:
- 在卡片的设置文档内( resources -> base -> profile -> form_config.json 文件 )
- 设置 isDynamic 选项
- false 表示非动态卡片( 静态卡片 ) 默认值
- true 表示动态卡片
- 动态的类型有三种 router call message
1.router类型
router 能力 => 拉起 Ability
- 1.1 卡片上设置一些按钮
Button('支付').onClick(() => this.clickHandler('pay'))Button('拍照').onClick(() => this.clickHandler('camera'))
- 1.2 点击按钮可以打开不同的页面
- 可以是相同的 UIAbility 的不同页面
- 也可以是不同 UIAbility 的不同页面
- 问题: 卡片可以调起 UIAbility,但是无法直接控制打开哪个页面,所以要在调起 UIAbility 的时候传递参数
// 卡片按钮事件 调起 UIAbility// 一定是唤起 EntryAbility, 给携带过去不同的参数( 把 Type 携带过去 ),在目标 EntryAbility 里, 解析参数, 然后打开对应的页面clickHandler(type: string): void {postCardAction(this, {action: 'router', // call( 首次启动的时候会触发 )abilityName: 'EntryAbility', // 目标 UIAbility 的名称params: { type }})}
// 目标 EntryAbility 解析参数, 然后打开对应的页面
// 1.设置变量 pageUrl
private cardPageUrl: string = 'pages/Index'
windowStage: window.WindowStage | null = null// 2.接受参数--传递的参数都 want 中
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {if (want?.parameters) {console.log('testLog onCreate 接受参数 =>', JSON.stringify(want.parameters))// 解析参数, 然后设置 pageUrl,因为我直接传了url过来,所以这里直接赋值this.cardPageUrl = (want?.parameters?.pageUrl as string) || 'pages/Index'}
}// 3.打开页面
onWindowStageCreate(windowStage: window.WindowStage): void {if (!this.windowStage) {this.windowStage = windowStage}windowStage.loadContent(this.cardPageUrl, (err) => {});
}
2.call类型
call 能力 => 首次启动会触发, 用于app在后台时操作,例如音乐播放器的上一首下一首按钮
-
注意1:使用 call 类型 需要开启权限 ohos.permission.KEEP_BACKGROUND_RUNNING
-
思路:
- 卡片与UIAbility 的数据存在 LocalStorage 内(与UiAbility 中 的 storage 不同,存在不同的地方)
- UIAbility与页面的参数传递就是通过 LocalStorage、AppStorage、globalThis 来进行的
-
2.1 卡片上设置一些按钮
// uiFlex({ justifyContent: FlexAlign.SpaceEvenly }) {Text('⏮️').fontSize(22).onClick(() => this.clickHandle(PlayerButtonType.PREV))Text(this.isSuspend ? '▶️' : '⏸️').fontSize(22).onClick(() => this.clickHandle(this.isSuspend ? PlayerButtonType.START : PlayerButtonType.STOP))Text('⏭️').fontSize(22).onClick(() => this.clickHandle(PlayerButtonType.NEXT))
}
- 2.2 点击按钮的时候,给 UIAbility 传递参数
// clickHandle 事件
clickHandle(type: PlayerButtonType) {postCardAction(this, {action: 'call',abilityName: 'EntryAbility',params: {method: 'music',type,}})
}
- 2.3 UIAbility 接受参数, 然后进行处理
- 在 EntryAbility 内, 监听 music 事件, 然后进行处理
- 监听的事件要跟 card 传递的 method一致
// 1.监听事件
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {try {this.callee.on('music', audioHandler)} catch (err) {console.log('wuwuwu 监听 catch =>', JSON.stringify(err))}
}// 2.处理数据
import { rpc } from '@kit.IPCKit';interface IParamsType {type: numberformId: string
}function audioHandler(data: rpc.MessageSequence) {// 参数在 data.readString() 内// 获取参数let params = JSON.parse(data.readString()) as IParamsType// 处理数据...// 处理完成数据通过 AppStorage、LocalStorage 等方式传递给 UIAbilityAppStorage.setOrCreate('audioIndex', audioIndex)// 使用固定的api更新card内数据,,此数据存储在LocalStroage内,供card使用const formInfo = formBindingData.createFormBindingData({ audioIndex })formProvider.updateForm(params.formId, formInfo)
}// 3.在card中 获取数据
@LocalStorageProp('audioIndex') audioIndex: number = 99// 4.在card中 展示数据
Text(this.audioIndex + '')
3.message类型
message 能力 => 刷新卡片内容
- 3.1 可以使用message拉起FormExtensionAbility,点击message类型按钮会触发FormExtensionAbility的onFormEvent生命周期,然后通过固定api更新数据,存在localStorage中,供card使用。
// 1.创建一个卡片按钮
Button('按钮').onClick(() => this.clickHandle())// 2.卡片按钮事件,message类型的参数都能在 onFormEvent 生命周期内获取到
clickHandle() {postCardAction(this, {action: 'message',abilityName: 'EntryAbility',params: { newVal: 'newVal'}})return null
}// 3.FormExtensionAbility 中 onFormEvent 做数据处理
onFormEvent(formId: string, message: string) {console.log(formId); // 1233112323 console.log( message); // {"newVal":"newVal","params":{"newVal":"newVal"},"action":"message"}// 初始化数据class updateFormData {testVal: string = 'newVall'}// 与 call 类型一样,调用固定的api更新card内数据,,此数据存储在LocalStroage内,供card使用const formData = formBindingData.createFormBindingData(new updateFormData())formProvider.updateForm(formId, formData).then((res) => {console.log('wuwuwu updateForm =>', res)}).catch((err: BusinessError) => {console.log('wuwuwu updateForm catch =>', JSON.stringify(err))})
}// 4.在card中 获取数据
@LocalStorageProp('testVal') testVal: string = 'initVal'// 5.在card中 展示数据
Text(this.testVal)
现在我也开始学习鸿蒙开发,欢迎大家一起交流学习