arkts-10 实战

一鸿蒙生态

  • 鸿蒙操作系统: 采用分布式架构设计微内核架构
  • 分布式软总线技术: 切换设备

七十 服务卡片介绍及创建

参考资料

70.1 卡片概念

抽取应用中你关注的功能, 放到卡片上, 以便添加到桌面上快捷使用

js 复制代码
长按app图标 -> 获取卡片列表/点击卡片 -> 进入卡片详情 -> 直接使用卡片
                                              ->  添加卡片到桌面 -> 以后便捷使用

70.2 卡片类型

静态卡片

  • 例如名言警句, 特点只能看, 最多点击跳转其他

动态卡片

  • 例如卡片页面 图片/内容刷新

互动卡片

  • 例如: 桌面卡片游戏

70.3 卡片相关文件及配置

js 复制代码
// 1 定义卡片声明周期
entry/src/main/ets/entryformability/EntryFormAbility.ets
js 复制代码
// 2 定义卡片样式
entry/src/main/ets/widget/pages/WidgetCard.ets
复制代码
js 复制代码
// 3 卡片配置信息 卡片名称 简介 刷新配置等
entry/src/main/resources/base/profile/form_config.json


{
  "forms": [
    {
     // want参数中的名称
      "name": "widget", 
      // 展示页面标题
      "displayName": "$string:widget_display_name",
      // 展示页面描述(灰色)
      "description": "$string:widget_desc", 
      // UI页配置路径
      "src": "./ets/widget/pages/WidgetCard.ets", 
      // 语法类型
      "uiSyntax": "arkts",
      // 设计尺寸基准
      "window": {
        "designWidth": 720,
        "autoDesignWidth": true
      },
      "colorMode": "auto",
      "isDynamic": true,
      "isDefault": true,
      "updateEnabled": false,
      "scheduledUpdateTime": "10:30", // 卡片内容刷新时间间隔
      "updateDuration": 1,
      "defaultDimension": "1*2",
      "supportDimensions": [ // 适配不同尺寸
        "1*2",
        "2*2"
      ]
    }
  ]
}
js 复制代码
// 4 让卡片与entry模块管关联, 让当前应用具备服务卡片能力
entry/src/main/module.json5

"module": {
   "extensionAbilities": [
  {
    "name": "EntryBackupAbility",
    "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
    "type": "backup",
    "exported": false,
    "metadata": [
      {
        "name": "ohos.extension.backup",
        "resource": "$profile:backup_config"
      }
    ],
  },
  {
    "name": "EntryFormAbility",
    "srcEntry": "./ets/entryformability/EntryFormAbility.ets",
    "label": "$string:EntryFormAbility_label",
    "description": "$string:EntryFormAbility_desc",
    "type": "form",
    "metadata": [
      {
        "name": "ohos.extension.form",
        "resource": "$profile:form_config"
      }
    ]
  }
 ]
}

70.4 服务卡片与页面交互

  • router事件
  • message事件
  • call事件

70.4.1 router事件

  • 点击卡片跳转至应用内页面的功能
  • 进入应用看看
js 复制代码
// UI 页创建两个按钮 A,B
// 点击按钮分别跳转到PageA, PageB页面

@Entry
@Component
struct WidgetCard {
  build() {
    Row() {
      Text('跳转A')
        .fontSize($r('app.float.font_size'))
        .fontWeight(FontWeight.Medium)
        .fontColor($r('sys.color.font'))
        .onClick(() => {
          postCardAction(this, {
            action: 'router',
            abilityName: 'EntryAbility',
            params: { targetPage: 'PageA' }
          });
        })
      Text('跳转B')
        .fontSize($r('app.float.font_size'))
        .fontWeight(FontWeight.Medium)
        .fontColor($r('sys.color.font'))
        .onClick(() => {
          postCardAction(this, {
            action: 'router',
            abilityName: 'EntryAbility',
            params: { targetPage: 'PageB' }
          });
        })

    }
    .width('100%')
    .justifyContent(FlexAlign.SpaceBetween)
    .height('100%')
    .backgroundColor($r('sys.color.comp_background_primary'))
  }
}
js 复制代码
// EntryAbility页面 配置跳转流程

export default class EntryAbility extends UIAbility {
  private selectPage = ''
  private currentWindowStage: window.WindowStage | null = null;  // 保存 windowStage 引用
  // 根据卡片传递的参数计算目标页面路径
  private getPagePath(): string {
    let path = 'view/pages/Index';
    if (this.selectPage === 'PageA') {
      path = 'view/pages/ServicePage/PageA';
    }
    if (this.selectPage === 'PageB') {
      path = 'view/pages/ServicePage/PageB';
    }
    return path;
  }

  // 获取服务卡片参数及跳转逻辑
  getServerCardParamAndJump(want: Want){
    if (want?.parameters?.params) { // 获取服务卡片参数
      let parmas: Record<string, Object> = JSON.parse(want?.parameters?.params as  string) as  Record<string, Object>
      this.selectPage = parmas.targetPage as string;
      console.log('-----onCreat---' + this.selectPage);
      // 关键:应用已在后台运行时,主动切换页面
      if (this.currentWindowStage !== null) {
        // 获取路径
        let path = this.getPagePath();
        // 路径跳转
        this.currentWindowStage.loadContent(path, (err: BusinessError) => {
          if (err.code) {
            return;
          }
        });
      }
    }
  }
  
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  // 服务卡片回调
  this.getServerCardParamAndJump(want)
}

// 点击卡片会触发
  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  // 服务卡片回调
    this.getServerCardParamAndJump(want)
}
  
}  

70.4.2 message事件

  • 可以使用router事件跳转到指定UIAbility,可以使用message拉起FormExtensionAbility,通过onFormEvent接口回调通知,以完成点击卡片控件后传递消息给应用的功能。
js 复制代码
// UI页 发送 message 消息, 
// 调用 FormExtensionAbility类的 onFormEvent 方法,更新数据类实现UI页面的更新

@Entry
@Component
struct WidgetCard {
  @LocalStorageProp('title') face: number = 1
  @LocalStorageProp('content') message: string = 'messgae-00'


  build() {
    Column() {
      this.messageBuild()
    }
    .size({width: '100%', height: '100%'})
  }

  @Builder
  messageBuild(){
    Text(this.message)
    Button().onClick(()=>{
      postCardAction(this, {
        action: 'message',
        abilityName: 'EntryAbility',
        params: {msgTest: 'messageEvent'}
      })
    })
  }
}
// 据说请求等操作不能放在这里写
js 复制代码
// FormExtensionAbility类

export default class EntryFormAbility extends FormExtensionAbility {

 // 发送message消息会调用这个方法
 onFormEvent(formId: string, message: string) {
  // 定义数据类
  class FormDataClass {
    title: number = 2
    content: string = ''
  }

  // 初始化数据类
  let formData = new FormDataClass()
  const param: Record<string, Object> = JSON.parse(message) as Record<string, Object>
  // formData.content = param['msgTest'] as string
  formData.content = message

  let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData)
  formProvider.updateForm(formId,formInfo) // 更新
    .then(()=>{

    })
    .catch(()=>{

    })
 }

}

ps: 坑爹的是断点不好使 onFormEvent~ 抓不到

70.4.3 call事件

  • 可以使用call事件拉起指定UIAbility到后台,再通过UIAbility申请对应后台长时任务完成音乐播放等功能。
  • 对比router前者需要打开应用, call则可以让应用在后台干活
js 复制代码
// 注意 module.json5 打开后台权限!!!
"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  },
  {
    "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" // 后台权限
  }
],
js 复制代码
// UI页面添加俩按钮 发送call消息
// EntryAbility 监听call消息

@Entry
@Component
struct WidgetCard {
  build() {
    Column() {
      this.callBuild() 
    }
    .size({width: '100%', height: '100%'})
  }
 
  @Builder
  callBuild(){
    Row() {
      Text('callA')
        .fontSize($r('app.float.font_size'))
        .fontWeight(FontWeight.Medium)
        .fontColor($r('sys.color.font'))
        .onClick(() => {
          postCardAction(this, {
            action: 'call',
            abilityName: 'EntryAbility',
            params: {
              num: 1,
              method: 'funA' }
          });
        })
      Text('callB')
        .fontSize($r('app.float.font_size'))
        .fontWeight(FontWeight.Medium)
        .fontColor($r('sys.color.font'))
        .onClick(() => {
          postCardAction(this, {
            action: 'call',
            abilityName: 'EntryAbility',
            params: {
              num: 1,
              method: 'funB' }
          });
        })
    }
    .width('100%')
    .justifyContent(FlexAlign.SpaceBetween)
    .height('100%')
    .backgroundColor($r('sys.color.comp_background_primary'))
  }

}
js 复制代码
// EntryAbility

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {

  // 监听服务卡片 call消息
  try {
    // 服务卡片回到 call
    this.callee.on('funA',(data: rpc.MessageSequence) => {
      console.log('funA触发了', JSON.stringify(data.readString()));// 注意这个readString必须加
      return new MyParcelable(1, '')
    })
    this.callee.on('funB',(data: rpc.MessageSequence) => {
      console.log('funB触发了', JSON.stringify(data.readString()));// 注意这个readString必须加
      return new MyParcelable(1, '')
    })
  } catch (error){
  }
}

70.4.4 应用内也可以调出服务卡片弹框

  • API18及以上, 可以应用内通过代码调出服务卡片
  • 等同于长按应用展示卡片弹框
相关推荐
范小兵1 小时前
# DevEco CLI实战:鸿蒙App「至客」从0开发到正式上架
前端·harmonyos
半生过往1 小时前
前端工程师学习智能体开发(一)
前端·学习·状态模式
白雾茫茫丶1 小时前
Vibecoding 一个主题切换动画库:13 种揭幕方式
前端·vue.js·react.js
计算机魔术师1 小时前
谷歌宣布 TPU 互联架构支持 100 万芯片规模,电力供应成 AI 基建核心瓶颈
前端
雪芽蓝域zzs1 小时前
第四十九节:TagsView 右键菜单(带三角箭头)给每个 tag 增加**鼠标右键菜单**(右键标签弹出:关闭、关闭其他、关闭全部)
前端·javascript·vue.js
এ慕ོ冬℘゜2 小时前
从零开发移动端医院挂号页面:适配、交互与前端实现详解
前端·javascript
熊猫钓鱼>_>2 小时前
声临其境:HarmonyOS 空间音频全链路开发实战
音频·harmonyos·arkts·鸿蒙·arkui·空间·hap
掘金挖土2 小时前
前端手摸手跑路之 AI 应用开发(六)
前端·后端
liuyt20222 小时前
【javaweb】day4
前端