鸿蒙卡片开发保姆级教程

卡片

1. 卡片概念

  1. 什么是卡片? 卡片用来显示或者提示一些基本信息或者进行一些基本操作。注意不能做重逻辑,所有重要逻辑全部交给应用
  2. 如果是元服务如何唤醒? 因为元服务不提供桌面应用图标,我们可以通过用户手动的方式在桌面上添加一张卡片,通过点击卡片来唤起元服务。

2. 创建卡片

  1. 在编辑器中创建

  2. 选择动态卡片




    卡片的特点
    1.卡片只能承载少量的内容和交互
    2. 卡片可以充当元服务icon作为入口,默认提供一张服务卡片作为入口
    3. 普通应用也可以添加服务卡片,但默认没有添加卡片

    元服务和普通应用的区别

  3. 添加卡片

3. ArkTS卡片实现原理

4. ArkTS卡片渲染服务运行原理

5. 卡片的服务通信

5.1 卡片-------> 应用
  • 使用postCardAction方法
  1. 在卡片pages中书写代码
typescript 复制代码
// 卡片的应用
@Entry
@Component
struct WidgetCard {
  @State count: number = 10;
  build() {
    Column() {
      Row({ space: 20 }) {
        Button('++')
          .onClick(() => {
            this.count++;

            postCardAction(this, {
              action: 'call',
              abilityName: 'EntryAbility',
              params: {
                method: 'updateFormCount',
                num: this.count
              }
            })
          })

        Text(this.count.toString())
          .fontSize(18)

        Button('--')
          .onClick(() => {
            if (this.count > 0) {
              this.count--;
              postCardAction(this,{
                action:'call',
                abilityName: 'EntryAbility',
                params:{
                  method:'updateFormCount',
                  num:this.count
                }
              })
            }
          })
      }
    }
    .width('100%')
    .height('100%')
    .onClick(() => {
    	// 点击唤醒应用
      postCardAction(this, {
        action: 'router',
        abilityName: 'EntryAbility'
      })
    })
  }
}
  1. module.json5添加-保持应用在后台权限
typescript 复制代码
 "requestPermissions": [{
      "name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
    }],
  1. 应用的entryability中进行接收
typescript 复制代码
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { rpc } from '@kit.IPCKit';
import { JSON } from '@kit.ArkTS';
import { preferences } from '@kit.ArkData';
import { formBindingData, formProvider } from '@kit.FormKit';

const DOMAIN = 0x0000;

//必须是rpc.Parcelable类型
class Params implements rpc.Parcelable {
  marshalling(dataOut: rpc.MessageSequence): boolean {
    return true;
  }

  unmarshalling(dataIn: rpc.MessageSequence): boolean {
    return true;
  }
}

class CardParams {
  count: number = 0
  formId:string = ""
}

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
    this.callee.on("updateFormCount", (data) => {
      const res = JSON.parse(data.readString()) as CardParams;
      AppStorage.setOrCreate('count', res.count);


	//必须返回一个rpc.Parcelable类型
      return new Params();
    })
  }

  onDestroy(): void {
  	//销毁时解除监听
    this.callee.off("updateFormCount")
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
        return;
      }
      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
    });
  }

  onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground(): void {
    // Ability has brought to foreground
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground(): void {
    // Ability has back to background
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
  }
}
  1. 主页Index.ets
typescript 复制代码
import { preferences } from '@kit.ArkData'
import { formBindingData, formProvider } from '@kit.FormKit'

@Component
@Entry
struct Index {
  @StorageLink('count')
  count:number = 0
  build() {
    Column(){
      Text('课程太多了')
        .fontSize(18)
        .fontColor(Color.Orange)
        .fontWeight(700)
      Row({ space: 20 }) {
        Button('++')
          .onClick(() => {
            this.count++;
          })

        Text(this.count.toString())
          .fontSize(18)

        Button('--')
          .onClick(() => {
            if (this.count > 0) {
              this.count--;
            }
          })
      }
    }
    .backgroundColor(Color.Pink)
    .width('100%')
    .height('100%')
  }
}

总结:如图示

5.2 应用----------->卡片
  1. 卡片的ability的entryformability的onAddForm方法中添加
typescript 复制代码
onAddForm(want: Want) {
    // Called to return a FormBindingData object.
    return formBindingData.createFormBindingData({
      formId: want.parameters!["ohos.extra.param.key.form_identity"] as string
    });
  }
  1. 卡片:WidgetCard.ets 监听formId ,当formId发生变化时,发送至应用
typescript 复制代码
 @LocalStorageProp("formId")
  @Watch("updateFormId")
  formId: string = ""

  updateFormId () {
    postCardAction(this, {
      action: 'call',
      abilityName: 'EntryAbility', // 只能跳转到当前应用下的UIAbility
      params: {
        method: 'updateFormId',
        formId: this.formId
      }
    })
  }
  1. 在ability中通过callee监听方法,将formId存入持久化
typescript 复制代码
 this.callee.on("updateFormId", (data) => {
      const res = JSON.parse(data.readString()) as CardParams
      const store = preferences.getPreferencesSync(this.context, {
        name: 'formIdList'
      })
      const list = JSON.parse(store.getSync("formIdList", "[]") as string) as string[]
      if(!list.includes(res.formId)) {
        list.push(res.formId)
      }
      store.putSync("formIdList", JSON.stringify(list))
      store.flush()
      formProvider.updateForm(res.formId, formBindingData.createFormBindingData({
        num: AppStorage.get("num")
      }))
      return new Params()
    })
  1. 卸载时解除
typescript 复制代码
  onDestroy(): void {
    this.callee.off("updateNum")
    this.callee.off("updateFormId")
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }
  1. Index.ets
typescript 复制代码
@StorageLink("num")
  @Watch("pushCard")
  num: number = 0

  pushCard() {
    const store = preferences.getPreferencesSync(getContext(), {
      name: 'formIdList'
    })
    const formIdList = JSON.parse(store.getSync("formIdList", "[]") as string) as string[]
    if (formIdList && formIdList.length) {
      formIdList.forEach((formId) => {
        formProvider.updateForm(formId, formBindingData.createFormBindingData({
          num: this.num
        }))
      })

    }
  }
  1. 卡片:从推送的数据中从新获取
typescript 复制代码
@Entry
@Component
struct WidgetCard {
  //修改成@LocalStorageProp
  @LocalStorageProp("count")  
  count: number = 0;
  @LocalStorageProp("formId")
  @Watch("updateFormId")
  formId:string = ""
  //应用===》卡片  需要把formId给到应用
  updateFormId(){
    postCardAction(this,{
      action:'call',
      abilityName: 'EntryAbility',
        params:{
          method:'updateFormId',
          formId:this.formId
        }
    })
  }

  build() {
    Column() {
      Row({ space: 20 }) {
        Button('++')
          .onClick(() => {
            this.count++;

            postCardAction(this, {
              action: 'call',
              abilityName: 'EntryAbility',
              params: {
                method: 'updateFormCount',
                count: this.count
              }
            })
          })

        Text(this.count.toString())
          .fontSize(18)
        Button('--')
          .onClick(() => {
            if (this.count > 0) {
              this.count--;
              postCardAction(this,{
                action:'call',
                abilityName: 'EntryAbility',
                params:{
                  method:'updateFormCount',
                  count:this.count
                }
              })
            }
          })
      }
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .width('100%')
    .height('100%')
    .onClick(() => {
      postCardAction(this, {
        action: 'router',
        abilityName: 'EntryAbility'
      })
    })
  }
}

总结:如图示:

相关推荐
zhanshuo10 小时前
手把手教你用 ArkUI 写出高性能分页列表:List + onScroll 实战解析
harmonyos
zhanshuo10 小时前
深入解析 ArkUI 触摸事件机制:从点击到滑动的开发全流程
harmonyos
i仙银15 小时前
鸿蒙沙箱浏览器 - SandboxFinder
app·harmonyos
Georgewu19 小时前
【HarmonyOS】鸿蒙应用开发中常用的三方库介绍和使用示例
harmonyos
AORO202521 小时前
遨游三防平板|国产芯片鸿蒙系统单北斗三防平板,安全高效
5g·安全·电脑·制造·信息与通信·harmonyos
软件开发技术深度爱好者1 天前
华为仓颉编程语言的表达式及其特点
华为·仓颉编程语言
蚊子爱喝水1 天前
HUAWEI Pura80系列机型参数对比
人工智能·华为
HarmonyOS小助手1 天前
“秒开”时代,HarmonyOS预加载让应用启动快如闪电
harmonyos·鸿蒙·鸿蒙生态
三翼鸟数字化技术团队2 天前
鸿蒙平台运行Lua脚本
lua·harmonyos