当前位置: 首页 > news >正文

鸿蒙卡片开发保姆级教程

卡片

1. 卡片概念

  1. 什么是卡片?

    卡片用来显示或者提示一些基本信息或者进行一些基本操作。注意不能做重逻辑,所有重要逻辑全部交给应用

  2. 如果是元服务如何唤醒?

    因为元服务不提供桌面应用图标,我们可以通过用户手动的方式在桌面上添加一张卡片,通过点击卡片来唤起元服务。

2. 创建卡片

  1. 在编辑器中创建
    卡片创建步骤

  2. 选择动态卡片
    在这里插入图片描述

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

    元服务和普通应用的区别
    在这里插入图片描述

  3. 添加卡片
    在这里插入图片描述
    在这里插入图片描述

3. ArkTS卡片实现原理

在这里插入图片描述

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

在这里插入图片描述

5. 卡片的服务通信

5.1 卡片-------> 应用
  • 使用postCardAction方法
  1. 在卡片pages中书写代码
// 卡片的应用
@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添加-保持应用在后台权限
 "requestPermissions": [{"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"}],
  1. 应用的entryability中进行接收
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 = 0formId: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 abilityhilog.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 resourceshilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground(): void {// Ability has brought to foregroundhilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');}
}
  1. 主页Index.ets
import { preferences } from '@kit.ArkData'
import { formBindingData, formProvider } from '@kit.FormKit'@Component
@Entry
struct Index {@StorageLink('count')count:number = 0build() {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方法中添加
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发生变化时,发送至应用
 @LocalStorageProp("formId")@Watch("updateFormId")formId: string = ""updateFormId () {postCardAction(this, {action: 'call',abilityName: 'EntryAbility', // 只能跳转到当前应用下的UIAbilityparams: {method: 'updateFormId',formId: this.formId}})}
  1. 在ability中通过callee监听方法,将formId存入持久化
 this.callee.on("updateFormId", (data) => {const res = JSON.parse(data.readString()) as CardParamsconst 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. 卸载时解除
  onDestroy(): void {this.callee.off("updateNum")this.callee.off("updateFormId")hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');}
  1. Index.ets
@StorageLink("num")@Watch("pushCard")num: number = 0pushCard() {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. 卡片:从推送的数据中从新获取
@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'})})}
}

总结:如图示:

在这里插入图片描述

http://www.lryc.cn/news/596235.html

相关文章:

  • AI创作系列第22篇:前端缓存与更新机制重构 - 表情包系统的全面升级
  • anchor 智能合约案例6 之 token_lottery
  • 假发行业数字化突围,外贸ERP重构外协管理引擎,助力效率飞跃
  • 34、鸿蒙Harmony Next开发:使用动画-转场动画
  • Jmeter使用 - 2
  • Chrome 开发环境屏蔽 CORS 跨域限制
  • PHICOMM(斐讯)N1盒子 - Armbian25.05(Debian 12)刷入U盘/EMMC
  • SQL 中 JOIN 顺序对性能的影响
  • FastDFS 6.11.0 单机环境搭建与测试(附 Nginx 集成)+ docker构建+k8s启动文件
  • 浏览器地址栏输入URL回车后白屏分析
  • Jenkins接口自动化测试(构建)平台搭建
  • Apache Ignite 中事务的使用方式和机制
  • Excel工具
  • ROS个人笔记
  • Qt Creator集成开发环境使用指南
  • K 近邻算法(K-Nearest Neighbors, KNN)详解及案例
  • 聊聊原生 CSS 变量:让样式更灵活的“魔法”
  • 大模型推理环境安装过程中踩坑记录
  • 野外具身视觉跟踪:北大团队TrackVLA让AI视觉跟踪进化到2.0时代
  • Springboot使用外部的Servelt容器(最简单的方式)
  • 1-bit AI 基础设施:第 1.1 部分 —— 在 CPU 上实现快速且无损的 BitNet b1.58 推理
  • ubuntu24.04安装CUDA、VLLM、Pytorch等并部署Qwen3-8B-AWQ【50系显卡通用】
  • proxmox 解决docker容器MongoDB创建报错MongoDB 5.0+ requires a CPU with AVX support
  • Leetcode力扣解题记录--第73题(矩阵置零)
  • Leetcode题解:209长度最小的子数组,掌握滑动窗口从此开始!!!
  • Vue中最简单的PDF引入方法及优缺点分析
  • Gradio, Streamlit, Dash:AI应用开发的效率之选
  • 配置https ssl证书生成
  • 拓展三字棋
  • ansible 批量 scp 和 load 镜像