鸿蒙OS开发实例:【手撸服务卡片】

介绍

服务卡片指导文档位于“开发/应用模型/Stage模型开发指导/Stage模型应用组件”路径下,说明其极其重要。

本篇文章将分享实现服务卡片的过程和代码

准备

  1. 请参照[官方指导],创建一个Demo工程,选择Stage模型
鸿蒙OS开发更多内容↓点击HarmonyOS与OpenHarmony技术
鸿蒙技术文档开发知识更新库gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md在这。或+mau123789学习,是v喔

搜狗高速浏览器截图20240326151547.png

  1. 熟读HarmonyOS 官方指导 “[创建一个ArkTS卡片]”

实践总结

  1. 应用打包时,不能选择“Deploy Muti Hap Packages”方式, 否则服务卡片不会显示任何内容
  2. 官方指导中没有提示添加权限“ohos.permission.KEEP_BACKGROUND_RUNNING”,如果不添加,则无法使用call方式来刷新卡片数据
  3. 卡片首次创建时,卡片Id无法传入到卡片中,需通过延时机制,二次更新

效果

Screenshot_20231201173024131.png

卡片元素说明

  1. 卡片共有使用到了7个控件
  2. 5个Text, 1个Image,  1个Rect
  3. Text('call') :  可点击,实验call事件刷新卡片内容
  4. Text('router'): 可点击,实验router事件刷新卡片内容
  5. Text('message'): 可点击,实验message事件刷新卡片内容
  6. Rect(): 实验卡片动画效果

服务卡片教程

  1. 请完全按照“创建一个ArkTS卡片”

  2. 修改生成的卡片代码(WidgetCard.ets)

let storageCard = new LocalStorage()@Entry(storageCard)
@Component
struct WidgetCard {/** The mini title.*/readonly MINI_TITLE: string = 'Title';/** The item title.*/@LocalStorageProp('ITEM_TITLE')ITEM_TITLE: string = '标题';/** The item content.*/@LocalStorageProp('ITEM_CONTENT') ITEM_CONTENT: string = '天气不错';/** The action type.*/readonly ACTION_TYPE: string = 'router';/** The ability name.*/readonly ABILITY_NAME: string = 'EntryAbility';/** The message.*/readonly MESSAGE: string = '来自服务卡片';/** The mini display priority.*/readonly MINI_DISPLAY_PRIORITY: number = 2;/** The max line.*/readonly MAX_LINES: number = 1;/** The with percentage setting.*/readonly FULL_WIDTH_PERCENT: string = '100%';/** The height percentage setting.*/readonly FULL_HEIGHT_PERCENT: string = '100%';/** Image height percentage setting.*/readonly IMAGE_HEIGHT_PERCENT: string = '64%';@State mini: boolean = false;@State rectWidth: string = '30%'@LocalStorageProp('formId') formId: string = '0';build() {Row() {Column() {if (this.mini) {Column() {Text(this.MINI_TITLE).fontSize($r('app.float.mini_title_font_size')).fontColor($r('app.color.mini_text_font_color')).margin({left: $r('app.float.mini_title_margin'),bottom: $r('app.float.mini_title_margin')})}.width(this.FULL_WIDTH_PERCENT).alignItems(HorizontalAlign.End).backgroundImageSize(ImageSize.Cover).backgroundImage($r("app.media.ic_widget"), ImageRepeat.NoRepeat).displayPriority(this.MINI_DISPLAY_PRIORITY)}Stack(){Image($r("app.media.ic_widget")).width(this.FULL_WIDTH_PERCENT).height('100%').objectFit(ImageFit.Cover).borderRadius($r('app.float.image_border_radius'))Rect().width(this.rectWidth).height('100%').fill('#60ff0000').animation({duration: 3000,curve: Curve.Linear,playMode: PlayMode.Normal,iterations: -1,onFinish:()=>{if(this.rectWidth == '30%'){this.rectWidth = '50%'} else {this.rectWidth = '30%'}}})Row(){Column({space: 20}){Text('call').fontColor(Color.Red).onClick(()=>{console.log('formId: '+this.formId)postCardAction(this, {'action': 'call','abilityName': 'EntryAbility','params': {'method': 'funA','formId': this.formId}});})Text('router').onClick(()=>{postCardAction(this, {'action': 'router','abilityName': 'EntryAbility','params': {'msgTest': 'messageEvent'}});})}Column(){Text('message').fontColor(Color.Green).onClick(()=>{postCardAction(this, {'action': 'message','params': {'msgTest': 'messageEvent'}});})}}.height('100%')}.width(this.FULL_WIDTH_PERCENT).height(this.IMAGE_HEIGHT_PERCENT)Blank()Text(this.ITEM_TITLE).fontSize($r('app.float.normal_title_font_size'))Text(this.ITEM_CONTENT).maxLines(this.MAX_LINES).fontSize($r('app.float.normal_content_font_size')).textOverflow({ overflow: TextOverflow.Ellipsis })}.width(this.FULL_WIDTH_PERCENT).height(this.FULL_HEIGHT_PERCENT).alignItems(HorizontalAlign.Start).backgroundColor($r('app.color.start_window_background'))}.height(this.FULL_HEIGHT_PERCENT).alignItems(VerticalAlign.Top).padding($r('app.float.row_padding')).onClick(() => {postCardAction(this, {"action": this.ACTION_TYPE,"abilityName": this.ABILITY_NAME,"params": {"message": this.MESSAGE}});})}
}
  1. 修改应用入口EntryAbility.ets
import window from '@ohos.window';
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 {storage: LocalStorageonCreate(want, launchParam) {try{let params = JSON.parse(want.parameters.params);console.log('onCreate ' + params['message'])this.storage = new LocalStorage({'ext': params['message']})} catch (e){console.log(e)}try{// 监听call事件所需的方法this.callee.on('funA', FunACall);} catch (e){console.log(e)}if (want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {let curFormId = want.parameters[formInfo.FormParam.IDENTITY_KEY];updateCardContent(curFormId, "EntryAbility", "router-welcome")}}onNewWant(want, launchParam) {try{let params = JSON.parse(want.parameters.params);console.log('onNewWant ' + params['message'])this.storage = new LocalStorage({'ext': params['message']})} catch (e){console.log(e)}}onWindowStageCreate(windowStage: window.WindowStage) {windowStage.loadContent('pages/Index', this.storage, (err, data) => {});}onDestroy(){console.log('onDestroy')// this.callee.off('funA')}}// 在收到call事件后会触发callee监听的方法
function FunACall(data) {// 获取call事件中传递的所有参数try{let params = JSON.parse(data.readString())if (params.formId !== undefined) {let curFormId = params.formId;updateCardContent(curFormId, "EntryAbility", "caller-welcome")}} catch (e){console.log(e)}return null;
}function updateCardContent(formId, method, content){let formData = {'ITEM_TITLE': method, // 和卡片布局中对应'ITEM_CONTENT': content, // 和卡片布局中对应};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));})
}
修改应用入入口页面Index.ets
let storage = new LocalStorage()@Entry(storage)
@Component
struct Page {@State message: string = 'Hello World'@LocalStorageProp('ext') extLocalStorageParms: string = '';aboutToAppear(){console.log(this.extLocalStorageParms)if(this.extLocalStorageParms){this.message = this.extLocalStorageParms}}build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}}
  1. 修改应用入入口页面Index.ets
let storage = new LocalStorage()@Entry(storage)
@Component
struct Page {@State message: string = 'Hello World'@LocalStorageProp('ext') extLocalStorageParms: string = '';aboutToAppear(){console.log(this.extLocalStorageParms)if(this.extLocalStorageParms){this.message = this.extLocalStorageParms}}build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}}
  1. 修改EntryFormAbility.ets
import formInfo from '@ohos.app.form.formInfo';
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 {onAddForm(want) {// Called to return a FormBindingData object.let formId = want.parameters["ohos.extra.param.key.form_identity"];let formData: Record<string, string> = {'formId': formId};console.log('onAddForm '+formId)let data = formBindingData.createFormBindingData(formData);setTimeout(()=>{formProvider.updateForm(formId, data).then((data) => {console.info('FormAbility updateForm success.' + JSON.stringify(data));}).catch((error) => {console.error('FormAbility updateForm failed: ' + JSON.stringify(error));})}, 1500)return data}onCastToNormalForm(formId) {// Called when the form provider is notified that a temporary form is successfully// converted to a normal form.console.log('onCastToNormalForm')}onUpdateForm(formId) {// Called to notify the form provider to update a specified form.console.log('onUpdateForm')}onChangeFormVisibility(newStatus) {// Called when the form provider receives form events from the system.console.log('onChangeFormVisibility')}onFormEvent(formId, message) {// Called when a specified message event defined by the form provider is triggered.console.log(message)this.updateCardContent(formId)}onRemoveForm(formId) {// Called to notify the form provider that a specified form has been destroyed.console.log('onRemoveForm')}onAcquireFormState(want) {// Called to return a {@link FormState} object.return formInfo.FormState.READY;}updateCardContent(formId){let formData = {'ITEM_TITLE': 'EntryFormAbility', // 和卡片布局中对应'ITEM_CONTENT': 'welcome', // 和卡片布局中对应};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));})}
};
  1. 在module.json5中添加权限
"requestPermissions": [{"name":  "ohos.permission.KEEP_BACKGROUND_RUNNING","usedScene": {"abilities": ["EntryAbility"],"when": "inuse"}}]

 7. 最后一步,请确认你的打包方式没有选择“Deploy Multi Hap Packages”,  否则将无法看到服务卡片内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/575750.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1学习使用axios

一、axios介绍&#xff1a; axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;用于浏览器和 Node.js。它提供了一种简单的方法来发送 HTTP 请求&#xff0c;并且具有很多实用的功能&#xff0c;使得网络请求变得更加方便和可靠。 以下是 axios 的一些主要特点和功能&…

Machine Learning机器学习之统计分析

目录 前言 机器学习之统计分析 统计学的主要目标包括&#xff1a; 统计学核心概念&#xff1a; 统计基础&#xff1a; 训练误差&#xff1a; 常见的损失函数&#xff1a; 正则化和交叉验证 博主介绍&#xff1a;✌专注于前后端、机器学习、人工智能应用领域开发的优质创作者、秉…

如何制作蛋糕店小程序_开启您的蛋糕店小程序之旅

甜蜜滋味&#xff0c;一触即达——开启您的蛋糕店小程序之旅 在这个快节奏的时代&#xff0c;人们对美食的追求从未停歇。尤其是那些色香味俱佳、口感细腻的蛋糕&#xff0c;更是成为了许多人生活中的小确幸。然而&#xff0c;忙碌的工作和生活常常让我们无法亲自前往蛋糕店&a…

关于web_server项目的学习记录(自用)

主要参考资料&#xff1a; 我在地铁吃闸机 基础处理框架&#xff1a;Multi-reactor muduo库有三个核心组件实现持续监听reactor的fd&#xff1a;channel;epoll/poller/eventloop类 channel 事件监听器epoll_ctl监听到了fd发生了什么事件,channel类会封装每个fd和fd感兴趣的事…

C# OpenCv Haar、LBP 人脸检测

目录 效果 代码 下载 效果 代码 using OpenCvSharp;namespace OPenCVDemo {class Program{static void Main(string[] args){// Load the cascadesvar haarCascade new CascadeClassifier("haarcascade_frontalface_default.xml");var lbpCascade new Casca…

网络原理-传输层-UDP报文结构

本文介绍UDP报文 有很多友友搞不清楚UDP报文的详细结构还有TCP的详细结构,所以专门分开来讲 以免弄混. 首先我们先看一下整个UDP结构,让大家有一个全方面的认识 下面我们来详细解释UDP报 16位源端口号(本机):就是2字节大小,16个二进制位. 16位目的端口号(目的机):也是2字节…

Ubuntu18.04安装wireshark

安装wireshark 环境Ubuntu18.04 1.使用root用户进行安装 2.将 wireshark-dev/stable PPA 添加到系统的软件源列表中。系统就可以从该PPA获取Wireshark软件包及其更新了。 apt-add-repository ppa:wireshark-dev/stable3.确保你系统上的软件包信息是最新的&#xff0c;这样在…

百度智能小程序源码系统简洁版 SEO关键词排名推广优化 带完整的安装代码包以及搭建教程

移动互联网的快速发展&#xff0c;小程序以其轻量级、无需下载、即用即走的特点&#xff0c;迅速成为了各大平台争相推广的重要产品形态。百度智能小程序作为百度生态下的重要一环&#xff0c;凭借其强大的流量入口和丰富的功能组件&#xff0c;为开发者提供了广阔的创作空间。…

百度智能云千帆,产业创新新引擎

本文整理自 3 月 21 日百度副总裁谢广军的主题演讲《百度智能云千帆&#xff0c;产业创新新引擎》。 各位领导、来宾、媒体朋友们&#xff0c;大家上午好。很高兴今天在石景山首钢园&#xff0c;和大家一起沟通和探讨大模型的发展趋势&#xff0c;以及百度最近一段时间的思考和…

灵动翻译音频文件字幕提取及翻译;剪映视频添加字幕

参考&#xff1a;视频音频下载工具 https://tuberipper.com/21/save/mp3 1、灵动翻译音频文件字幕提取及翻译 灵动翻译可以直接chorme浏览器插件安装&#xff1a; 点击使用&#xff0c;可以上传音频文件 上传后自动翻译&#xff0c;然后点击译文即可翻译成中文&#xff0c;…

软件概要设计说明书word原件(实际项目)

一、 引言 &#xff08;一&#xff09; 编写目的 &#xff08;二&#xff09; 范围 &#xff08;三&#xff09; 文档约定 &#xff08;四&#xff09; 术语 二、 项目概要 &#xff08;一&#xff09; 建设背景 &#xff08;二&#xff09; 建设目标 &#xff08;三&a…

Svg Flow Editor 原生svg流程图编辑器(四)

系列文章 Svg Flow Editor 原生svg流程图编辑器&#xff08;一&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;二&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;三&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;四&#xf…