鸿蒙HarmonyOS实战-Stage模型(开发卡片事件)

🚀一、开发卡片事件

HarmonyOS元服务卡片页面(Metaservice Card Page)是指在HarmonyOS系统中,用于展示元服务的页面界面。元服务是指一组提供特定功能或服务的组件,例如天气服务、音乐播放服务等。元服务卡片页面可以显示元服务的相关信息和操作选项,用户可以通过点击卡片页面上的按钮或交互元素来使用相关的元服务功能。元服务卡片页面提供了一种快速访问和使用元服务的方式,方便用户进行各种操作和任务。

🔎1.卡片事件能力说明

postCardAction()接口是ArkTS卡片中用于实现卡片内部和提供方应用间交互的方法。目前这个接口支持三种类型的事件:router、message和call,并且仅在卡片中可以调用。

  • router类型的事件可以用来执行页面跳转或路由切换的操作。通过指定目标路由和传递参数,可以实现页面之间的跳转或路由切换。

  • message类型的事件用于发送消息或通知给提供方应用。可以通过指定目标应用和消息内容,向提供方应用发送消息或通知。

  • call类型的事件用于调用提供方应用的函数或方法。可以通过指定目标应用、要调用的函数或方法名以及传递的参数,调用提供方应用中的函数或方法。

postCardAction()接口仅在卡片内部可以调用,无法在提供方应用中直接调用。这个接口提供了卡片和提供方应用之间进行交互的方式,可以实现卡片的功能扩展和与提供方应用的数据交互。

🔎2.使用router事件跳转到指定UIAbility

1、元服务界面

@Entry
@Component
struct WidgetCard {
  build() {
    Column() {
      Button('功能A')
        .margin('20%')
        .onClick(() => {
          console.info('Jump to EntryAbility funA');
          postCardAction(this, {
            'action': 'router',
            'abilityName': 'EntryAbility', // 只能跳转到当前应用下的UIAbility
            'params': {
              'targetPage': 'funA' // 在EntryAbility中处理这个信息
            }
          });
        })

      Button('功能B')
        .margin('20%')
        .onClick(() => {
          console.info('Jump to EntryAbility funB');
          postCardAction(this, {
            'action': 'router',
            'abilityName': 'EntryAbility', // 只能跳转到当前应用下的UIAbility
            'params': {
              'targetPage': 'funB' // 在EntryAbility中处理这个信息
            }
          });
        })
    }
    .width('100%')
    .height('100%')
  }
}

2、UIAbility接收参数

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';

let selectPage = "";
let currentWindowStage = null;

export default class CameraAbility extends UIAbility {
  // 如果UIAbility第一次启动,在收到Router事件后会触发onCreate生命周期回调
  onCreate(want, launchParam) {
    // 获取router事件中传递的targetPage参数
    console.info("onCreate want:" + JSON.stringify(want));
    if (want.parameters.params !== undefined) {
      let params = JSON.parse(want.parameters.params);
      console.info("onCreate router targetPage:" + params.targetPage);
      selectPage = params.targetPage;
    }
  }
  // 如果UIAbility已在后台运行,在收到Router事件后会触发onNewWant生命周期回调
  onNewWant(want, launchParam) {
    console.info("onNewWant want:" + JSON.stringify(want));
    if (want.parameters.params !== undefined) {
      let params = JSON.parse(want.parameters.params);
      console.info("onNewWant router targetPage:" + params.targetPage);
      selectPage = params.targetPage;
    }
    if (currentWindowStage != null) {
      this.onWindowStageCreate(currentWindowStage);
    }
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    let targetPage;
    // 根据传递的targetPage不同,选择拉起不同的页面
    switch (selectPage) {
      case 'funA':
        targetPage = 'pages/FunA';
        break;
      case 'funB':
        targetPage = 'pages/FunB';
        break;
      default:
        targetPage = 'pages/Index';
    }
    if (currentWindowStage === null) {
      currentWindowStage = windowStage;
    }
    windowStage.loadContent(targetPage, (err, data) => {
      if (err && err.code) {
        console.info('Failed to load the content. Cause: %{public}s', JSON.stringify(err));
        return;
      }
    });
  }
};

🔎3.使用call事件拉起指定UIAbility到后台

1、元服务界面

@Entry
@Component
struct WidgetCard {
  build() {
    Column() {
      Button('功能A')
        .margin('20%')
        .onClick(() => {
          console.info('call EntryAbility funA');
          postCardAction(this, {
            'action': 'call',
            'abilityName': 'EntryAbility', // 只能跳转到当前应用下的UIAbility
            'params': {
              'method': 'funA' // 在EntryAbility中调用的方法名
            }
          });
        })
       Button('功能B')
        .margin('20%')
        .onClick(() => {
          console.info('call EntryAbility funB');
          postCardAction(this, {
            'action': 'call',
            'abilityName': 'EntryAbility', // 只能跳转到当前应用下的UIAbility
            'params': {
              'method': 'funB', // 在EntryAbility中调用的方法名
              'num': 1 // 需要传递的其他参数
            }
          });
        })
    }
    .width('100%')
    .height('100%')
  }
}

2、UIAbility接收参数

import UIAbility from '@ohos.app.ability.UIAbility';
 
function FunACall(data) {
  // 获取call事件中传递的所有参数
  console.log('FunACall param:' + JSON.stringify(data.readString()));
  return null;
}
 function FunBCall(data) {
  console.log('FunACall param:' + JSON.stringify(data.readString()));
  return null;
}
 
export default class CameraAbility extends UIAbility {
  // 如果UIAbility第一次启动,在收到call事件后会触发onCreate生命周期回调
  onCreate(want, launchParam) {
      try {
          // 监听call事件所需的方法
          this.callee.on('funA', FunACall);
          this.callee.on('funB', FunBCall);
      } catch (error) {
          console.log('register failed with error. Cause: ' + JSON.stringify(error));
      }
  }
   
  // 进程退出时,解除监听
  onDestroy() {
      try {
          this.callee.off('funA');
          this.callee.off('funB');
      } catch (error) {
          console.log('register failed with error. Cause: ' + JSON.stringify(error));
      }
  }
};

不截图同上

🔎4.通过message事件刷新卡片内容

1、卡片页面

let storage = new LocalStorage();

@Entry(storage)
@Component
struct WidgetCard {
  @LocalStorageProp('title') title: string = 'init';
  @LocalStorageProp('detail') detail: string = 'init';

  build() {
    Column() {
      Button('刷新')
        .onClick(() => {
          postCardAction(this, {
            'action': 'message',
            'params': {
              'msgTest': 'messageEvent'
            }
          });
        })
      Text(`${this.title}`)
      Text(`${this.detail}`)
    }
    .width('100%')
    .height('100%')
  }
}

2、卡片FormExtensionAbility

import formBindingData from '@ohos.app.form.formBindingData';
import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility';
import formProvider from '@ohos.app.form.formProvider';

export default class EntryFormAbility extends FormExtensionAbility {
  onFormEvent(formId, message) {
    // Called when a specified message event defined by the form provider is triggered.
    console.info(`FormAbility onEvent, formId = ${formId}, message: ${JSON.stringify(message)}`);
    let formData = {
      'title': 'Title Update Success.', // 和卡片布局中对应
      'detail': 'Detail Update Success.', // 和卡片布局中对应
    };
    let formInfo = formBindingData.createFormBindingData(formData)
    formProvider.updateForm(formId, formInfo).then((data) => {
      console.info('FormAbility updateForm success.' + JSON.stringify(data));
    }).catch((error) => {
      console.error('FormAbility updateForm failed: ' + JSON.stringify(error));
    })
  }
}

🔎5.通过router或call事件刷新卡片内容

🦋5.1 router

1、卡片

let storage = new LocalStorage();

@Entry(storage)
@Component
struct WidgetCard {
  @LocalStorageProp('detail') detail: string = 'init';

  build() {
    Column() {
      Button('跳转')
        .margin('20%')
        .onClick(() => {
          console.info('postCardAction to EntryAbility');
          postCardAction(this, {
            'action': 'router',
            'abilityName': 'EntryAbility', // 只能跳转到当前应用下的UIAbility
            'params': {
              'detail': 'RouterFromCard'
            }
          });
        })
      Text(`${this.detail}`).margin('20%')
    }
    .width('100%')
    .height('100%')
  }
}

2、UIAbility

import UIAbility from '@ohos.app.ability.UIAbility';
import formBindingData from '@ohos.app.form.formBindingData';
import formProvider from '@ohos.app.form.formProvider';
import formInfo from '@ohos.app.form.formInfo';

export default class EntryAbility extends UIAbility {
  // 如果UIAbility第一次启动,在收到Router事件后会触发onCreate生命周期回调
  onCreate(want, launchParam) {
    console.info('Want:' + JSON.stringify(want));
    if (want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {
      let curFormId = want.parameters[formInfo.FormParam.IDENTITY_KEY];
      let message = JSON.parse(want.parameters.params).detail;
      console.info(`UpdateForm formId: ${curFormId}, message: ${message}`);
      let formData = {
        "detail": message + ': onCreate UIAbility.', // 和卡片布局中对应
      };
      let formMsg = formBindingData.createFormBindingData(formData)
      formProvider.updateForm(curFormId, formMsg).then((data) => {
        console.info('updateForm success.' + JSON.stringify(data));
      }).catch((error) => {
        console.error('updateForm failed:' + JSON.stringify(error));
      })
    }
  }
  // 如果UIAbility已在后台运行,在收到Router事件后会触发onNewWant生命周期回调
  onNewWant(want, launchParam) {
    console.info('onNewWant Want:' + JSON.stringify(want));
    if (want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {
      let curFormId = want.parameters[formInfo.FormParam.IDENTITY_KEY];
      let message = JSON.parse(want.parameters.params).detail;
      console.info(`UpdateForm formId: ${curFormId}, message: ${message}`);
      let formData = {
        "detail": message + ': onNewWant UIAbility.', // 和卡片布局中对应
      };
      let formMsg = formBindingData.createFormBindingData(formData)
      formProvider.updateForm(curFormId, formMsg).then((data) => {
        console.info('updateForm success.' + JSON.stringify(data));
      }).catch((error) => {
        console.error('updateForm failed:' + JSON.stringify(error));
      })
    }
  }

  ...
}

🦋5.2 call

1、在使用postCardAction接口的call事件时,需要在FormExtensionAbility中的onAddForm生命周期回调中更新formId。

import formBindingData from '@ohos.app.form.formBindingData'; 
import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility';

export default class EntryFormAbility extends FormExtensionAbility {
  onAddForm(want) {
   let formId = want.parameters["ohos.extra.param.key.form_identity"];
   let dataObj1 = {
     "formId": formId
   };
   let obj1 = formBindingData.createFormBindingData(dataObj1);
   return obj1;
 }
    
 ...
};

2、卡片界面

let storage = new LocalStorage();

@Entry(storage)
@Component
struct WidgetCard {
  @LocalStorageProp('detail') detail: string = 'init';
  @LocalStorageProp('formId') formId: string = '0';

  build() {
    Column() {
      Button('拉至后台')
        .margin('20%')
        .onClick(() => {
          console.info('postCardAction to EntryAbility');
          postCardAction(this, {
            'action': 'call',
            'abilityName': 'EntryAbility', // 只能跳转到当前应用下的UIAbility
            'params': {
              'method': 'funA',
              'formId': this.formId,
              'detail': 'CallFromCard'
            }
          });
        })
      Text(`${this.detail}`).margin('20%')
    }
    .width('100%')
    .height('100%')
  }
}
let storage = new LocalStorage();

@Entry(storage)
@Component
struct WidgetCard {
  @LocalStorageProp('detail') detail: string = 'init';
  @LocalStorageProp('formId') formId: string = '0';

  build() {
    Column() {
      Button('拉至后台')
        .margin('20%')
        .onClick(() => {
          console.info('postCardAction to EntryAbility');
          postCardAction(this, {
            'action': 'call',
            'abilityName': 'EntryAbility', // 只能跳转到当前应用下的UIAbility
            'params': {
              'method': 'funA',
              'formId': this.formId,
              'detail': 'CallFromCard'
            }
          });
        })
      Text(`${this.detail}`).margin('20%')
    }
    .width('100%')
    .height('100%')
  }
}

3、UIAbility界面

import UIAbility from '@ohos.app.ability.UIAbility';
import formBindingData from '@ohos.app.form.formBindingData';
import formProvider from '@ohos.app.form.formProvider';
import formInfo from '@ohos.app.form.formInfo';
const MSG_SEND_METHOD: string = 'funA'
 
// 在收到call事件后会触发callee监听的方法
function FunACall(data) {
  // 获取call事件中传递的所有参数
  let params = JSON.parse(data.readString())
  if (params.formId !== undefined) {
    let curFormId = params.formId;
    let message = params.detail;
    console.info(`UpdateForm formId: ${curFormId}, message: ${message}`);
    let formData = {
      "detail": message
    };
    let formMsg = formBindingData.createFormBindingData(formData)
    formProvider.updateForm(curFormId, formMsg).then((data) => {
      console.info('updateForm success.' + JSON.stringify(data));
    }).catch((error) => {
      console.error('updateForm failed:' + JSON.stringify(error));
    })
  }
  return null;
}
export default class EntryAbility extends UIAbility {
  // 如果UIAbility第一次启动,call事件后会触发onCreate生命周期回调
  onCreate(want, launchParam) {
    console.info('Want:' + JSON.stringify(want));
    try {
       // 监听call事件所需的方法
      this.callee.on(MSG_SEND_METHOD, FunACall);
    } catch (error) {
      console.log(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`)
    }
  }
  ...
}

🚀写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY
相关推荐
努力变厉害的小超超4 小时前
ArkTS中的组件基础、状态管理、样式处理、class语法以及界面渲染
笔记·鸿蒙
sanzk4 小时前
华为鸿蒙应用开发
华为·harmonyos
SoraLuna8 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
ClkLog-开源埋点用户分析9 小时前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos
mg6689 小时前
鸿蒙系统的优势 开发 环境搭建 开发小示例
华为·harmonyos
lqj_本人10 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人10 小时前
使用 Flutter 绘制一个棋盘
harmonyos
lqj_本人13 小时前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
青瓷看世界14 小时前
华为HarmonyOS打造开放、合规的广告生态 - 插屏广告
华为·harmonyos·广告投放
青瓷看世界14 小时前
华为HarmonyOS借助AR引擎帮助应用实现虚拟与现实交互的能力2-管理AR会话
华为·ar·harmonyos·虚拟现实