鴻蒙HarmonyOS實戰-Stage模型(開發卡片事件)

蜀道山QAQ發表於2024-05-20

🚀一、開發卡片事件

HarmonyOS元服務卡片頁面(Metaservice Card Page)是指在HarmonyOS系統中,用於展示元服務的頁面介面。元服務是指一組提供特定功能或服務的元件,例如天氣服務、音樂播放服務等。元服務卡片頁面可以顯示元服務的相關資訊和操作選項,使用者可以透過點選卡片頁面上的按鈕或互動元素來使用相關的元服務功能。元服務卡片頁面提供了一種快速訪問和使用元服務的方式,方便使用者進行各種操作和任務。

🔎1.卡片事件能力說明

postCardAction()介面是ArkTS卡片中用於實現卡片內部和提供方應用間互動的方法。目前這個介面支援三種型別的事件:router、message和call,並且僅在卡片中可以呼叫。

  • router型別的事件可以用來執行頁面跳轉或路由切換的操作。透過指定目標路由和傳遞引數,可以實現頁面之間的跳轉或路由切換。

  • message型別的事件用於傳送訊息或通知給提供方應用。可以透過指定目標應用和訊息內容,向提供方應用傳送訊息或通知。

  • call型別的事件用於呼叫提供方應用的函式或方法。可以透過指定目標應用、要呼叫的函式或方法名以及傳遞的引數,呼叫提供方應用中的函式或方法。

postCardAction()介面僅在卡片內部可以呼叫,無法在提供方應用中直接呼叫。這個介面提供了卡片和提供方應用之間進行互動的方式,可以實現卡片的功能擴充套件和與提供方應用的資料互動。

image

🔎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%')
  }
}

image

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;
      }
    });
  }
};

image

🔎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));
    })
  }
}

image

🔎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

image

相關文章