鸿蒙 ArkTS 应用截图全指南:从组件到离屏长图全搞定
在鸿蒙 ArkTS 应用开发中,截图并不是个边缘需求,而是有非常多实用场景的关键能力:
- 👨💻 UI 自动化测试
- 🧾 内容卡片、年度报告生成
- 📤 用户分享长图、社交素材
- 🐞 用户反馈、崩溃回溯、复现问题
- 🎨 离屏渲染组件进行预览或保存
鸿蒙框架提供了强大的截图 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<image.PixelMap>`,可以链式调用 `.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)
}
🧮 2. 计算 totalHeight(必须)
const baseHeight = 120; // 标题 + padding 预留
const itemHeight = 60; // 每一项高度
this.totalHeight = baseHeight + this.achievements.length * itemHeight;
🚀 3. 生成截图:
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) => {
// 一整张页面图像,适合反馈或全屏渲染内容
});
💡 PixelMap 用法拓展
你拿到的是 image.PixelMap
类型,它可以用于:
Image(pixmapSrc)
直接展示;- 调用
.getPixelBytes()
拿原始像素数据; - 使用
ImagePacker
或媒体 API 转换成 PNG 并保存; - 转成 Base64 上传或在 WebView 显示;
⚙️ 示例:保存成本地图片文件(需要写文件权限)可参考官方 image.ImagePacker
接口。
🧠 实战建议:截图模块如何组织?
场景 | 方法 | 建议 |
---|---|---|
页面中已加载组件 | SnapshotUtil.get(id) | 设置 .id() ,组件必须已挂载 |
需要动态生成卡片或隐藏组件截图 | SnapshotUtil.createFromBuilder(...) | 使用 @Builder ,必须设置 .height(...) |
全屏快照 | SnapshotUtil.snapshot() | 可配合崩溃记录、状态保存 |
🔚 小结
鸿蒙 ArkTS 提供了截图相关非常完善的 API,通过封装一个简洁的 SnapshotUtil
工具类,你就可以快速适配:
- ✅ 组件截图
- ✅ 离屏渲染生成卡片
- ✅ 长图内容分享
- ✅ 窗口截图反馈
灵活配合业务逻辑,你可以轻松实现一系列创意玩法:UI视觉比对、年度报告生成、社交图卡渲染、用户反馈截图、客服问题复现等。