鸿蒙开发:分享弹窗
在鸿蒙应用开发里,实现图片分享功能,对提升用户体验有着极大的帮助。它能让用户更自由地处理图片,满足大家在不同场景下的需求。从应用自身价值来看,这个功能就像是给应用添了一对翅膀。而且,它还能增强用户对应用的依赖度,让用户更愿意留在这个应用里,从而提高应用的竞争力,在众多应用中脱颖而出。最后有完整代码。
鸿蒙开发:分享弹窗
注:适用版本(HarmonyOS NEXT/5.0/API12+)
在鸿蒙应用开发里,实现图片分享功能,对提升用户体验有着极大的帮助。它能让用户更自由地处理图片,满足大家在不同场景下的需求。从应用自身价值来看,这个功能就像是给应用添了一对翅膀。而且,它还能增强用户对应用的依赖度,让用户更愿意留在这个应用里,从而提高应用的竞争力,在众多应用中脱颖而出。
这次分享一个只需要临时请求的保存权限(代码中颜色请自己替换谢谢)
分享弹窗组件
目的: 定义一个分享弹窗组件,点击分享打开
会使用到一个二维码组件 QRCode
实现步骤:
- 自定义Dialog
a. 名称: QuestionShareDialog, 接收试题对象 item
b. 获取用户信息 - 布局组件
a. 堆叠容器 (底部对齐, 裁剪, 圆角)
b. Column组件, Row组件
QuestionShareDialog.ets
import { UserStoreKey } from '../../commons/utils/Auth'
import { QuestionDetail, User } from '../../models'
@CustomDialog
export struct QuestionShareDialog {
@Prop item: QuestionDetail
@StorageProp(UserStoreKey) user: User = {} as User
controller: CustomDialogController //必须要有
build() {
Stack({ alignContent: Alignment.BottomEnd }) {
Column({ space: 20 }) {
Image($r('代码中图片请自己替换谢谢'))
.width(40)
.height(40)
Text('搞定企业面试题')
Divider()
.strokeWidth(0.5)
.color($r('代码中颜色请自己替换谢谢'))
Text('大厂面试题:' + this.item.stem)
.fontSize(12)
.maxLines(2)
.fontWeight(600)
.width('100%')
.lineHeight(24)
.textOverflow({ overflow: TextOverflow.Ellipsis })
QRCode(this.item.id)
.width(160)
.height(160)
.alignSelf(ItemAlign.Center)
Text('扫码查看答案')
.fontSize(12)
.alignSelf(ItemAlign.Center)
Blank()
Text('分享来自:' + this.user.nickName || this.user.username)
.fontSize(12)
}
.id('share') // 用于后续截图使用
.padding(20)
.alignItems(HorizontalAlign.Start)
.width(300)
.height(500)
.backgroundColor($r('app.color.white'))
Row() {
Text('保存到本地')
.fontColor($r('app.color.white'))
.fontSize(14)
.padding(12)
.backgroundColor($r('代码中颜色请自己替换谢谢'))
}
.borderRadius({ topLeft: 8 })
.clip(true)
}
.borderRadius(8)
.clip(true)
}
}
注:这里是自定义弹窗QuestionPage.ets
shareDialog = new CustomDialogController({
builder: QuestionShareDialog({ item: this.item }),//内容
customStyle: true,//开启自定义弹窗
alignment: DialogAlignment.Center //位置
})
在哪里使用点击他
MenuItem({ content: '分享' })
.onClick(() => this.shareDialog.open())
组件截屏
目标:分享弹窗截图并缓存到缓存目录
前置知识:
componentSnapShot
get(id: string, options?: SnapshotOptions): Promise<image.PixelMap>
获取已加载的组件的截图,传入组件的组件标识,找到对应组件进行截图。通过Promise返回结果。
ImagePacker
packing(source: PixelMap, option: PackingOption): Promise<ArrayBuffer>
图片压缩或重新打包,使用Promise形式返回结果。
实现步骤:
- 方法名称: saveImage
- 使用
componentSnapShot组件截图的get方法,得到 PixelMap 像素图像数据 - 使用
ImagePacker打包 PixelMap 数据,转成二进制 ArrayBuffer 图片数据 - 将 ArrayBuffer 图片数据写入缓存目录,生成图片
- 获取上下文
- 定义图片的存储路径
ctx.cacheDir + '/' + Date.now() + '.jpeg' - 通过fileIo以 创建 或 读写 的方式打开文件
- 通过fileIo同步把二进制数据写入文件
- 同步关闭文件
- 提示用户
/**
1. 保存图片到沙箱, 再从沙箱中读取写入相册
*/
async saveImage() {
// 1. 根据组件的id生成截图对象
const pixelMap = await componentSnapshot.get('share')
// 2. 借助ImagePacker去把图片对象生成二级制数据流
const imagePacker = image.createImagePacker()
const arrayBuffer = await imagePacker.packToData(pixelMap, { format: "image/jpeg", quality: 98 })
// 3. 借助fileIo读写文件
// 3.1 获取上下文
const ctx = getContext(this)
// 3.2 获取沙箱中存图的路径
const imagePath = ctx.cacheDir + '/' + Date.now() + '.jpeg'
// 3.3 以 创建 或 读写 的模式打开文件(没有则创建并打开, 有则打开)
const file = fileIo.openSync(imagePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
// 3.4 同步写入二级制数据流到文件中
fileIo.writeSync(file.fd, arrayBuffer)
// 3.5 同步去关闭文件
fileIo.closeSync(file.fd)
promptAction.showToast({ message: '保存成功' })
}
Text('保存到本地')
.fontColor($r('app.color.white'))
.fontSize(14)
.padding(12)
.backgroundColor($r('代码中颜色请自己替换谢谢'))
.onClick(() => {
this.saveImage()
})
现在就保存到了沙箱中
沙箱在Device File Browser > data > app > el2 > 100 > base > 包名

保存到相册
目标:将沙箱缓存目录中的文件保存到相册
前置知识点:
- photoAccessHelper 该模块提供相册管理模块能力,包括创建相册以及访问、修改相册中的媒体数据信息等。
- SaveButton 安全控件的保存控件,用户通过点击该保存按钮,可以临时获取存储权限,而不需要权限弹框授权确认。
实现步骤:
- 使用
fileUri.getUriFromPath()获取uri地址 - 使用
photoAccessHelper模块发起资源变更请求,存储图片到相册- 创建实例对象
photoAccessHelper.getPhotoAccessHelper(ctx) - 调用方法
applyChanges
- 创建实例对象
- 使用
SaveButton安全组件获取短时权限,进行相册操作- 判断用户成功授权
- 处理按钮图标/文字/样式
...
// 3.5 同步去关闭文件
fileIo.closeSync(file.fd)
// 4. 把沙箱中的文件写入相册
// 4.1 获取资源文件的uri地址
const imgUrl = fileUri.getUriFromPath(imagePath)
// 4.2 进行图片资产变更(私有->公有)
const assetChangeRequest = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(ctx, imgUrl);
// 4.3 提交媒体变更请求
// 4.3.1 获取相册管理模块的实例
const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(ctx)
// 4.3.2 调用变更方法
// 需要配置权限: permission: ohos.permission.WRITE_IMAGEVIDEO
await phAccessHelper.applyChanges(assetChangeRequest);
// 5. 关闭弹窗
this.controller.close()
promptAction.showToast({ message: '图片写入相册成功' })
注:之前的Text换成SaveButton
SaveButton({
icon: SaveIconStyle.FULL_FILLED,//设置保存按钮的图标风格
text: SaveDescription.SAVE_IMAGE,//设置保存按钮的文本描述
buttonType: ButtonType.Normal//设置保存按钮的背景样式
})
.fontColor($r('app.color.white'))
.fontSize(14)
.padding(12)
.backgroundColor($r('代码中颜色请自己替换谢谢'))
.onClick((event: ClickEvent, result: SaveButtonOnClickResult) => {
//如果用户点击授权
if (result === SaveButtonOnClickResult.SUCCESS) {
this.saveImage()
}
})
展望
展望未来,随着鸿蒙系统的不断发展和普及,图片保存和分享功能肯定会变得更强大、更便捷。从系统层面来看,可能会提供更简洁、更强大的 API 。比如说,在权限管理方面,以后说不定系统能自动帮我们处理权限申请的复杂逻辑,开发者不用再为权限申请的细节操心,只要专注于功能实现就好,这能大大提高开发效率,让开发过程变得更轻松。
更多推荐



所有评论(0)