Harmony OS 卡片能力
注意:
- 把 卡片 分成两种
- 静态卡片: 不允许其他事件的触发( 只能进行整体事件触发 ), 并且需要使用 FormLink 组件包裹
- 动态卡片: 可以触发其他事件, 但是不能使用 FromLink 来触发拉起 Ability
- 如何设置:
- 在卡片的设置文档内( resources -> base -> profile -> form_config.json 文件 )
- 设置 isDynamic 选项
- false 表示非动态卡片( 静态卡片 ) 默认值
- true 表示动态卡片
- 动态的类型有三种 router call message
1.router类型
router 能力 => 拉起 Ability
- 1.1 卡片上设置一些按钮
ts
Button('支付').onClick(() => this.clickHandler('pay'))
Button('拍照').onClick(() => this.clickHandler('camera'))
- 1.2 点击按钮可以打开不同的页面
- 可以是相同的 UIAbility 的不同页面
- 也可以是不同 UIAbility 的不同页面
- 问题: 卡片可以调起 UIAbility,但是无法直接控制打开哪个页面,所以要在调起 UIAbility 的时候传递参数
ts
// 卡片按钮事件 调起 UIAbility
// 一定是唤起 EntryAbility, 给携带过去不同的参数( 把 Type 携带过去 ),在目标 EntryAbility 里, 解析参数, 然后打开对应的页面
clickHandler(type: string): void {
postCardAction(this, {
action: 'router', // call( 首次启动的时候会触发 )
abilityName: 'EntryAbility', // 目标 UIAbility 的名称
params: { type }
})
}
ts
// 目标 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 卡片上设置一些按钮
ts
// ui
Flex({ 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 传递参数
ts
// clickHandle 事件
clickHandle(type: PlayerButtonType) {
postCardAction(this, {
action: 'call',
abilityName: 'EntryAbility',
params: {
method: 'music',
type,
}
})
}
- 2.3 UIAbility 接受参数, 然后进行处理
- 在 EntryAbility 内, 监听 music 事件, 然后进行处理
- 监听的事件要跟 card 传递的 method一致
ts
// 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: number
formId: string
}
function audioHandler(data: rpc.MessageSequence) {
// 参数在 data.readString() 内
// 获取参数
let params = JSON.parse(data.readString()) as IParamsType
// 处理数据
...
// 处理完成数据通过 AppStorage、LocalStorage 等方式传递给 UIAbility
AppStorage.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使用。
ts
// 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)
现在我也开始学习鸿蒙开发,欢迎大家一起交流学习