【HarmonyOS ArkTS】获取组件截图并保存到相册

写在前面

本文基于项目中的文件,详细说明组件截图及保存到相册的实现逻辑。 适合 HarmonyOS 开发初学者理解如何在 ArkTS 中完成组件截图、图片保存至缓存路径与图片保存至相册的操作。

一、整体流程

  1. 对特定组件截图
  2. 将图片压缩并写入到缓存目录
  3. 将图片保存到本地相册

二、代码实现

typescript 复制代码
// 模块导入
import { componentSnapshot, promptAction } from "@kit.ArkUI"
import { image } from "@kit.ImageKit"
import { fileIo, fileUri } from "@kit.CoreFileKit"
import { photoAccessHelper } from "@kit.MediaLibraryKit"

async saveImg() {
  // 1. 对特定组件截图
  const pixelMap = await componentSnapshot.get('share')
  
  // 2. 将图片压缩并写入到缓存目录
  const packer = image.createImagePacker()
  const arrayBuffer = await packer.packToData(pixelMap, { format: 'image/jpeg', quality: 70 })
  const cxt = getContext()
  const imgPath = cxt.cacheDir + '/' + Date.now() + '.jpeg'
  const imgFile =
    fileIo.openSync(imgPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
  fileIo.closeSync(imgFile)
  
  // 3. 将图片保存到本地相册
  const imgUri = fileUri.getUriFromPath(imgPath)
  const request = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(cxt, imgUri)
  const helper = photoAccessHelper.getPhotoAccessHelper(cxt)
  await helper.applyChanges(request)

  promptAction.showToast({ message: '图片已保存到本地' })
}

三、结构说明

1. 对特定组件截图

typescript 复制代码
import { componentSnapshot } from "@kit.ArkUI"

@Component
struct PreviewComponent {
  @State id: string = 'share';

  build() {
    Column() {
      // 需要截图的组件
      Image($r('app.media.banner'))
        .id(this.id)
        
      Button('保存截图')
        .onClick(() => this.saveImg())
    }
  }

 async saveImg() {
   // 1. 对特定组件截图
   const pixelMap = await componentSnapshot.get('share')

  //......
 }
}

说明:

  • 将需要截图的组件的id填入componentSnapshot.get的参数中
  • 结果为pixelMap格式的图片数据

2. 将图片压缩并写入到缓存目录

typescript 复制代码
import { image } from "@kit.ImageKit"
import { fileIo } from "@kit.CoreFileKit"


async saveImg() {
  //......
  
  // 2. 将图片压缩并写入到缓存目录
  // image.createImagePacker()函数的返回值是ImagePacker对象
  const packer = image.createImagePacker()
  // 将图片压缩或重新编码,返回的结果为二进制数据流
  const arrayBuffer = await packer.packToData(pixelMap, { format: 'image/jpeg', quality: 70 }) // 图片质量(1-100)

  // 获取缓存路径
  const cxt = getContext()
  const imgPath = cxt.cacheDir + '/' + Date.now() + '.jpeg'

  // 创建临时文件对象,给fileIo创建和写入权限,写入压缩后的图片数据
  const imgFile =
    fileIo.openSync(imgPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
  // 将图片写入到缓存路径
  fileIo.writeSync(imgFile.fd, arrayBuffer)
  // 关闭后file对象不再具备实际意义 不可再用于进行读写等操作
  fileIo.closeSync(imgFile)

  //......
}

说明:

  • 使用 ImagePacker 对pixelMap格式数据进行压缩并打包
  • 使用 fileIo 模块将图片写入到缓存目录
  • 操作完后注意关闭file对象

3. 将图片保存到本地相册

typescript 复制代码
import { promptAction } from "@kit.ArkUI"
import { fileUri } from "@kit.CoreFileKit"
import { photoAccessHelper } from "@kit.MediaLibraryKit"

async saveImg() {
  //......
  
  // 3. 将图片保存到本地相册
  // 获取图片的完整路径( getContext获取的是部分路径 )
  const imgUri = fileUri.getUriFromPath(imgPath)
  // 创建一个 向相册发送修改数据 的请求
  const request = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(cxt, imgUri)

  // 获取照片访问助手实例,用于接收请求
  const helper = photoAccessHelper.getPhotoAccessHelper(cxt)

  // 调用助手实例上的方法, 将图片保存到本地 ( 需要相册的相关权限 )
  await helper.applyChanges(request)

  promptAction.showToast({ message: '图片已保存到本地' })
}

说明:

  • 使用 fileUri 获取图片的完整路径
  • 通过 photoAccessHelper 模块得到修改请求和图片访问助手
  • 将图片保存到本地 ( 需要相册的相关权限 )

四、相关模块说明

模块 功能
componentSnapshot 对已渲染的组件进行截图
promptAction 创建并显示文本提示框
image 提供图片的解码和编码能力
fileIo 提供文件存储管理能力
fileUri 通过PATH获取文件统一资源标志符
photoAccessHelper 提供相册管理能力

五、补充

如果没有向用户申请相册的相关权限,我们也可以用华为内置的安全控件完成保存功能,此时用户通过点击该保存按钮,可以临时获取存储权限,而不需要权限弹框授权确认。

typescript 复制代码
// 
 SaveButton({
          text: SaveDescription.SAVE_IMAGE,
          buttonType: ButtonType.Normal,
          icon: SaveIconStyle.FULL_FILLED
        })
          .onClick((event, result) => {
            if (result == SaveButtonOnClickResult.SUCCESS) {
              this.saveImg()
              // 自己关自己
              this.controller.close()
            }
          })

为了保障用户的隐私不被恶意应用获取,华为针对安全控件作了很多的限制,比如其对象参数内属性的值都是枚举,开发者并不能对其样式做过多更改。

六、总结

本文提供了一个获取组件截图并保存到相册的主要流程,并提供了一个临时获取相册存储权限的方式,希望能帮助开发者快速掌握保存图片的核心代码实现。

相关推荐
贾伟康10 小时前
HarmonyOS API 26 DevEco Code 需求到 ArkTS 骨架的提示词分层
harmonyos·arkts·ai coding·deveco code·工程提效
贾伟康15 小时前
HarmonyOS API 26 HMAF Skill 可解释任务计划与失败回退
harmonyos·arkts·智能体·skill·hmaf
贾伟康16 小时前
HarmonyOS API 26 HMAF 2.0 意图解析的可解释动作图
harmonyos·arkts·智能体·a2a·hmaf
贾伟康20 小时前
HarmonyOS API 26 Navigation 菜单项刷新态:stale 数据、重试与一致性
harmonyos·arkts·arkui·navigation·多设备
贾伟康2 天前
【共创稿事节】HarmonyOS 7.0 Progress进度体系:从接入到生产验证
性能优化·实战·harmonyos·arkts·arkui
贾伟康2 天前
HarmonyOS API 26 HMAF Skill 端侧 A2A 消息去重与上下文最小化
harmonyos·arkts·skill·a2a·hmaf
贾伟康2 天前
HarmonyOS API 26 HMAF Skill 多 Skill 冲突仲裁与可恢复执行
harmonyos·arkts·智能体·skill·hmaf
贾伟康7 天前
【共创稿事节】HarmonyOS 7.0 BindContentCover全屏模态:从接入到生产验证
性能优化·实战·harmonyos·arkts·arkui
贾伟康7 天前
【共创稿事节】HarmonyOS 7.0 Menu菜单与上下文:从接入到生产验证
性能优化·实战·harmonyos·arkts·arkui
行者-全栈开发7 天前
Flutter 插件 device_calendar_plus 开源鸿蒙适配实战:从权限弹窗失灵到循环日程跑通
flutter·跨平台·harmonyos·arkts·日历·适配·开源鸿蒙