HarmonyOS Next 实战卡片开发 02

server/2024/11/15 1:28:26/

HarmonyOS Next 实战卡片开发 02

卡片开发中,还有一个难点是显示图片。其中分为显示本地图片和显示网络图片

显示本地图片

卡片可以显示本地图片,如存放在应用临时目录下的图片。路径比如

/data/app/el2/100/base/你的项目boundleName/temp/123.png

以下操作是为了得到一张 该目录下的图片做的准备工作

  1. 截图,得到一张相册图片
  2. 使用PhotoViewPicker来选择要操作的图片
  3. 复制该图片到应用的临时目录下
  4. 传递给卡片组件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图,得到一张相册图片

使用PhotoViewPicker来选择要操作的图片

在首页中,选择要操作的图片,获得该文件的uri地址

entry/src/main/ets/pages/Index.ets

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
import { promptAction } from '@kit.ArkUI';@Entry
@Component
struct Index {async aboutToAppear() {// 创建一个新的 PhotoSelectOptions 实例来配置图片选择器的行为let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();// 设置 MIME 类型为图像类型,这样用户只能选择图像文件PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;// 设置用户可以选择的最大图片数量为 1 张PhotoSelectOptions.maxSelectNumber = 1;// 创建一个新的 PhotoViewPicker 实例,用于打开图片选择器let photoPicker = new photoAccessHelper.PhotoViewPicker();// 使用前面配置好的选项打开图片选择器,并等待用户完成选择// 注意这里的 select 方法是一个异步方法,所以需要使用 await 关键字等待其结果const PhotoSelectResult = await photoPicker.select(PhotoSelectOptions);// 获取用户选择的第一张图片的 URI(统一资源标识符)// 假设这里只关心用户选择的第一张图片// uri file://media/Photo/3/IMG_1729864738_002/screenshot_20241025_215718.jpgconst uri = PhotoSelectResult.photoUris[0];promptAction.showToast({ message: `${uri}` })}build() {RelativeContainer() {}.height('100%').width('100%')}
}

复制该图片到应用的临时目录下

目标是将刚才的图片复制到应用的临时目录下,为最后的卡片显示本地图片做准备

image-20241025220456712

在刚才的代码下,接着实现

    // 获取应用的临时目录let tempDir = getContext(this).getApplicationContext().tempDir;// 生成一个新的文件名const fileName = 123 + '.png'// 通过缓存路径+文件名 拼接出完整的路径const copyFilePath = tempDir + '/' + fileName// 将文件 拷贝到 临时目录const file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY)fileIo.copyFileSync(file.fd, copyFilePath)

传递给卡片组件

在当前的环节中,有一个需要特别需要注意的地方,就是构造合适的数据。比如以下的数据

image-20241025221558917

然后在创建卡片的时候,在Ability中读取图片地址,拼接参数,传递给卡片

entry/src/main/ets/entryformability/EntryFormAbility.ets

import { Want } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { formBindingData, FormExtensionAbility } from '@kit.FormKit';export default class EntryFormAbility extends FormExtensionAbility {// 在添加卡片时,打开一个本地图片并将图片内容传递给卡片页面显示onAddForm(want: Want): formBindingData.FormBindingData {// 假设在当前卡片应用的tmp目录下有一个本地图片 123.pnglet tempDir = this.context.getApplicationContext().tempDir;let imgMap: Record<string, number> = {};// 打开本地图片并获取其打开后的fdlet file = fileIo.openSync(tempDir + '/' + '123.png');imgMap['imgBear'] = file.fd;class FormDataClass {// 卡片需要显示图片场景, 必须和下列字段formImages 中的key 'imgBear' 相同。imgName: string = 'imgBear';// 卡片需要显示图片场景, 必填字段(formImages 不可缺省或改名), 'imgBear' 对应 fdformImages: Record<string, number> = imgMap;}let formData = new FormDataClass();console.log("formDataformData", JSON.stringify(formData))// 将fd封装在formData中并返回至卡片页面return formBindingData.createFormBindingData(formData);}
}

卡片需要 使用 'memory://+this.imgName' 来显示图片

let storageWidgetImageUpdate = new LocalStorage();@Entry(storageWidgetImageUpdate)
@Component
struct WidgetImageUpdateCard {@LocalStorageProp('imgName') imgName: ResourceStr = "";build() {Column() {}.width('100%').height('100%').backgroundImage('memory://' + this.imgName).backgroundImageSize(ImageSize.Cover)}
}

完整效果

小结

  1. 截图,得到一张相册图片
  2. 使用PhotoViewPicker来选择要操作的图片
  3. 复制该图片到应用的临时目录下
  4. 传递给卡片组件

以上的前三步骤都是为了得到临时图片,实际开发中根据情况来获取即可

还有

  • Image组件通过入参(memory://fileName)中的(memory://)标识来进行远端内存图片显示,其中fileName需要和EntryFormAbility传递对象(‘formImages’: {key: fd})中的key相对应。
  • Image组件通过传入的参数是否有变化来决定是否刷新图片,因此EntryFormAbility每次传递过来的imgName都需要不同,连续传递两个相同的imgName时,图片不会刷新。
  • 在卡片上展示的图片,大小需要控制在2MB以内。

显示网络图片

卡片中不支持直接显示网络图片如以下方式是不支持的

Image("https://cn-assets.gitee.com/assets/mini_app-e5eee5a21c552b69ae6bf2cf87406b59.jpg")

我们需要申请网络权限,然后将图片下载下来,最后再重复类似卡片显示本地图片的步骤即可

  1. 申请网络权限

    entry/src/main/module.json5

    image-20241025225743062

  2. 设置网络图片地址

  3. 使用http开始下载

  4. 写入文件

  5. 返回给卡片组件

entry/src/main/ets/entryformability/EntryFormAbility.ets

import { Want } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';export default class EntryFormAbility extends FormExtensionAbility {// 在添加卡片时,打开一个本地图片并将图片内容传递给卡片页面显示onAddForm(want: Want) {// 注意:FormExtensionAbility在触发生命周期回调时被拉起,仅能在后台存在5秒// 建议下载能快速下载完成的小文件,如在5秒内未下载完成,则此次网络图片无法刷新至卡片页面上const formId = want.parameters![formInfo.FormParam.IDENTITY_KEY] as stringlet netFile ='https://env-00jxhf99mujs.normal.cloudstatic.cn/card/3.webp?expire_at=1729871552&er_sign=0eb3f6ac3730703039b1565b6d3e59ad'; // 需要在此处使用真实的网络图片下载链接let httpRequest = http.createHttp()// 下载图片httpRequest.request(netFile).then(async (data) => {if (data?.responseCode == http.ResponseCode.OK) {// 拼接图片地址let tempDir = this.context.getApplicationContext().tempDir;let fileName = 'file' + Date.now();let tmpFile = tempDir + '/' + fileName;let imgMap: Record<string, number> = {};class FormDataClass {// 卡片需要显示图片场景, 必须和下列字段formImages 中的key fileName 相同。imgName: string = fileName;// 卡片需要显示图片场景, 必填字段(formImages 不可缺省或改名), fileName 对应 fdformImages: Record<string, number> = imgMap;}// 打开文件let imgFile = fileIo.openSync(tmpFile, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);imgMap[fileName] = imgFile.fd;// 写入文件await fileIo.write(imgFile.fd, data.result as ArrayBuffer);let formData = new FormDataClass();let formInfo = formBindingData.createFormBindingData(formData);// 下载完网络图片后,再传递给卡片formProvider.updateForm(formId, formInfo)fileIo.closeSync(imgFile);httpRequest.destroy();console.log("============")}}).catch((e: BusinessError) => {console.log("eeee", e.message)})class FormData {formId: string = ""}// 先返回基本数据return formBindingData.createFormBindingData(new FormData);}onFormEvent(formId: string, message: string): void {}
}

作者

作者:万少

链接:https://www.nutpi.net/

來源:坚果派 著作权归作者所有。

商业转载请联系作者获得授权,非商业转载请注明出处。


http://www.ppmy.cn/server/141986.html

相关文章

比ChatGPT更酷的AI工具

相较于寻找比ChatGPT更酷的AI工具&#xff0c;这听起来似乎是个挑战&#xff0c;因为ChatGPT已经以它强大的综合性能在AI界大名鼎鼎。然而&#xff0c;每个工具都有其独特的优势&#xff0c;特别是在特定的应用场景下&#xff0c;其他AI工具可能会展现出与ChatGPT不同的魅力。接…

基于springboot+vue框架的在线考试系统设计与实现(lw+源码+代码解释+视频演示)

您好&#xff0c;我是码农飞哥&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通&#x1f601; 2. 毕业…

Openshift 如何更新访问控制机

OPenshift 安装的时候会指定用于访问集群的访问机&#xff0c; 比如PC1的ssh key 为key1, 那key1会配置到集群的ISO中&#xff0c; 那后如果PC1重新装OS 或者想换成其他的电脑是&#xff0c; key1 可以为变成key2. 我们只需要用machineConfig就可以轻松更新。 步骤 如下&…

DOCKER 镜像基础命令

目录 1. 查看镜像列表 2. 拉取镜像 3. 推送镜像到仓库 4. 保存镜像到文件 5. 导出镜像并压缩 6. 加载镜像文件 7. 标记镜像&#xff08;重命名&#xff09; 8. 检查镜像信息 9. 构建新镜像 10. 删除镜像 11. 清除dangling和不再使用的镜像 12. 将一台主机的所有镜像…

spring boot 统一异常处理

在Spring Boot中&#xff0c;可以使用ControllerAdvice注解创建一个全局异常处理类&#xff0c;来处理应用程序中发生的各种异常。以下是一个简单的例子&#xff1a; import org.springframework.http.HttpStatus; import org.springframework.web.bind.MethodArgumentNotVal…

昇思大模型平台打卡体验活动:项目1基于MindSpore实现BERT对话情绪识别

基于MindSpore实现BERT对话情绪识别 1. 模型简介 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是由Google于2018年末开发并发布的一种新型语言模型&#xff0c;基于Transformer架构中的Encoder&#xff0c;并且具有双向编码的特性。…

Linux基础之病毒编写

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 声明&#xff1a;本文主要用作技术分享&#xff0c;所有内容仅供参考。任何使用或依赖于本文信息所造成的法律后果均与本人无关。请读者自行判断风险&#xff0c;并遵循相关法律法规。 感谢泷…

vue项目,实现跨系统跳转免登录,点击链接直接进入项目首页,有token则免登录,否则就跳转到登录页

目前我用的是vue-admin-better框架&#xff0c; 实现的功能是&#xff0c;在地址后面拼接个token&#xff0c;如果有token&#xff0c;则直接跳转到首页&#xff0c;若没有token&#xff0c;则跳转到登录页面&#xff0c;实现跨系统跳转免登录 其实很简单&#xff0c;首先考虑…