在鸿蒙 ArkTS 应用开发中,截图并不是个边缘需求,而是有非常多实用场景的关键能力:
鸿蒙框架提供了强大的截图 API,配合封装良好的 SnapshotUtil
工具类,截图可以变得简单、高效、适配各种业务场景。
SnapshotUtil
完整实现(优化版)这里是一个适配 ArkTS 使用的截图封装工具类,涵盖了组件截图、离屏截图、窗口截图。
import { image } from '@kit.ImageKit';
import { componentSnapshot, window } from '@kit.ArkUI';
import { AppUtil } from './AppUtil'; // 用于获取上下文和主窗口
export class SnapshotUtil {
private constructor() {}
/**
* 获取当前 UI 上指定组件的截图(要求组件已加载且设置了 id)
* @param id 组件唯一 id(通过 .id() 设置)
*/
static get(id: string): Promise<image.PixelMap> {
const context = AppUtil.getUIContext();
if (!context) {
return Promise.reject('No UI context found');
}
return context.getComponentSnapshot().get(id);
}
/**
* 离屏渲染一个自定义组件并截图(支持长图)
* @param builder 一个带 @Builder 标记的组件构建函数
*/
static createFromBuilder(builder: () => void): Promise<image.PixelMap> {
const context = AppUtil.getUIContext();
if (!context) {
return Promise.reject('No UI context found');
}
return context.getComponentSnapshot().createFromBuilder(builder);
}
/**
* 对整个应用窗口截图(可传入具体 window 或自动获取主窗口)
* @param win 可选:要截图的窗口实例
*/
static snapshot(win?: window.Window): Promise<image.PixelMap> {
const targetWin = win ?? AppUtil.getMainWindow();
if (!targetWin) {
return Promise.reject('No Window instance available');
}
return targetWin.snapshot();
}
}
````
### ✅ 补充说明:
* `AppUtil.getUIContext()`:你需要在项目中封装这个方法,返回 `UIAbilityContext` 实例;
* `AppUtil.getMainWindow()`:返回当前主窗口 `Window` 实例;
* 所有返回类型都是 `Promise `,可以链式调用 `.then(...)`
---
## 离屏截图组件示例(支持长图)
### ✅ 1. 先写一个带 `@Builder` 的 UI 构造函数
```ts
@Builder
buildLongCard() {
Column() {
Text(' 成就卡片')
.fontSize(26)
.fontWeight(FontWeight.Bold)
.padding({ top: 20, bottom: 10 })
ForEach(this.achievements, (item, index) => {
Row() {
Text(`#${index + 1}`)
.fontColor(Color.Gray)
.width(50)
Text(item.title)
.fontColor(Color.White)
.fontSize(20)
}
.padding({ top: 8, bottom: 8 })
})
Text('数据更新:' + this.today)
.fontSize(14)
.fontColor(Color.Gray)
.margin({ top: 30 })
}
.width('90%')
.height(this.totalHeight) // 重点:高度要动态算!
.backgroundColor(Color.Black)
.padding(20)
}
const baseHeight = 120; // 标题 + padding 预留
const itemHeight = 60; // 每一项高度
this.totalHeight = baseHeight + this.achievements.length * itemHeight;
SnapshotUtil.createFromBuilder(this.buildLongCard.bind(this)).then((pixelMap) => {
// 拿到长图 pixelMap,后续可以保存、展示或上传
});
// 假设组件设置了唯一 id
Text('页面内组件')
.id('myComponent')
.fontColor(Color.Red)
SnapshotUtil.get('myComponent').then((pixelMap) => {
// 截到指定组件图像
});
// 当前主窗口截图
SnapshotUtil.snapshot().then((pixelMap) => {
// 一整张页面图像,适合反馈或全屏渲染内容
});
你拿到的是 image.PixelMap
类型,它可以用于:
Image(pixmapSrc)
直接展示;.getPixelBytes()
拿原始像素数据;ImagePacker
或媒体 API 转换成 PNG 并保存;⚙️ 示例:保存成本地图片文件(需要写文件权限)可参考官方 image.ImagePacker
接口。
场景 | 方法 | 建议 |
---|---|---|
页面中已加载组件 | SnapshotUtil.get(id) |
设置 .id() ,组件必须已挂载 |
需要动态生成卡片或隐藏组件截图 | SnapshotUtil.createFromBuilder(...) |
使用 @Builder ,必须设置 .height(...) |
全屏快照 | SnapshotUtil.snapshot() |
可配合崩溃记录、状态保存 |
鸿蒙 ArkTS 提供了截图相关非常完善的 API,通过封装一个简洁的 SnapshotUtil
工具类,你就可以快速适配:
灵活配合业务逻辑,你可以轻松实现一系列创意玩法:UI视觉比对、年度报告生成、社交图卡渲染、用户反馈截图、客服问题复现等。