当前位置: 首页 > news >正文

HarmonyOS 离屏截图实战:createFromBuilder 动态生成图片的完整流程

文章目录

    • 背景
      • 方法总览
      • 什么是离屏渲染?
      • 第一步:定义顶层 @Builder 函数
      • 第二步:调用 createFromBuilder
      • checkImageStatus 参数的作用
      • 截图结果显示
      • delay 怎么设合适?
      • 完整代码示例
      • createFromBuilder vs get(),怎么选?
      • 写在最后

背景

近期发现一款很有意思的HarmonyOS 三方库, 地址 @pura/harmony-utils(V1.4.0) , 作者是"桃花镇童长老", 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦

案例demo导航展示

↓↓↓↓↓↓接下来言归正传 ↓↓↓↓
上一篇讲了用get()截取已经显示在屏幕上的组件。但有时候你需要生成一张图片,这张图片对应的 UI 组件并不需要显示给用户看,只是用来生成图片内容——比如分享卡片、动态生成海报。

这种场景就需要用到createFromBuilder:离屏渲染。

方法总览

什么是离屏渲染?

正常的 UI 渲染是把组件画到屏幕上,用户能看到。离屏渲染是把组件"画"在一块内存缓冲区里,用户看不到,但我们可以把这块缓冲区的内容转成图片。

整个流程是:

  1. 定义一个@Builder函数描述 UI 内容
  2. 调用createFromBuilder,把这个 Builder 传进去
  3. 系统在内存里渲染这个 UI
  4. 截取内存里的内容,返回PixelMap
  5. 你拿到PixelMap可以显示、保存、上传

第一步:定义顶层 @Builder 函数

关键点createFromBuilder接受的是顶层@Builder函数(不是 struct 里的@Builder方法),必须定义在 struct 外面。

// 必须定义在组件 struct 外部@BuilderfunctionbuilderParam(){Column({space:6}){Text('SnapshotUtil 离屏渲染示例').fontSize(16).fontColor('#FFFFFF').fontWeight(FontWeight.Bold)Text('createFromBuilder 截图内容').fontSize(12).fontColor('#CCFFCC')Row({space:6}){Circle({width:20,height:20}).fill('#FF6B6B')Circle({width:20,height:20}).fill('#4ECDC4')Circle({width:20,height:20}).fill('#FFE66D')}}.width(260).height(100).backgroundColor('#2C3E50').borderRadius(12).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}

这个 Builder 定义了一张深色背景、有文字和彩色圆圈的小卡片。它不会显示在屏幕上,只用于离屏渲染。

第二步:调用 createFromBuilder

createFromBuilder接受三个参数:

  • 第一个:@Builder函数引用
  • 第二个:delay(延迟毫秒数),让组件有时间完成渲染
  • 第三个:checkImageStatus(是否检查图片加载状态)
this.Btn('createFromBuilder(builderParam, delay=300)','#9B59B6',()=>{SnapshotUtil.createFromBuilder(builderParam,300,false).then(pm=>{this.builderPixelMap=pm;this.addLog(`createFromBuilder() → PixelMap${pm.getPixelBytesNumber()}bytes`);}).catch((e:Error)=>{this.addLog(`createFromBuilder() Error:${e.message}`);});})

delay=300的意思是等待 300 毫秒再截图,给系统时间完成布局和渲染。

checkImageStatus 参数的作用

如果 Builder 里包含Image组件(比如从网络加载的图片),图片加载是异步的,截图时图片可能还没加载完。这时候把checkImageStatus设为true,系统会等图片加载完毕再截图:

this.Btn('createFromBuilder(builderParam, delay=500, checkImageStatus=true)','#8E44AD',()=>{SnapshotUtil.createFromBuilder(builderParam,500,true).then(pm=>{this.builderPixelMap=pm;this.addLog(`createFromBuilder(delay=500) →${pm.getPixelBytesNumber()}bytes`);}).catch((e:Error)=>{this.addLog(`createFromBuilder Error:${e.message}`);});})

delay=500, checkImageStatus=true:等 500ms 并检查图片状态,适合 Builder 里有网络图片的情况。

截图结果显示

拿到PixelMap后,用Image组件显示:

if(this.builderPixelMap!==undefined){this.SectionTitle('离屏截图预览')Image(this.builderPixelMap).width('100%').height(120).objectFit(ImageFit.Contain).backgroundColor('#F0F0F0').borderRadius(8)}

delay 怎么设合适?

这个值没有固定标准,要根据 Builder 里的内容复杂程度来决定:

Builder 内容建议 delay
只有文字和基本图形200~300ms
有本地图片资源300~500ms
有网络图片(配合 checkImageStatus=true)500~1000ms
复杂布局+多张图片800ms+

设太小可能截到空白内容,设太大用户等待时间长。建议先用 300ms 试,如果有空白内容就加长。

完整代码示例

import{SnapshotUtil}from'../Utils/SnapshotUtil';import{image}from'@kit.ImageKit';@Entry@Componentstruct CreateFromBuilderDemo{@StatebuilderPixelMap:image.PixelMap|undefined=undefined;build(){Column({space:12}){Button('生成离屏截图').onClick(()=>{SnapshotUtil.createFromBuilder(builderParam,300,false).then(pm=>{this.builderPixelMap=pm;}).catch((e:Error)=>{console.error('离屏截图失败:',e.message);});})if(this.builderPixelMap!==undefined){Text('离屏截图结果:').fontSize(13).fontColor('#888')Image(this.builderPixelMap).width('100%').height(120).objectFit(ImageFit.Contain).backgroundColor('#F0F0F0').borderRadius(8)}}.padding(16)}}// Builder 必须定义在 struct 外部@BuilderfunctionbuilderParam(){Column({space:6}){Text('SnapshotUtil 离屏渲染示例').fontSize(16).fontColor('#FFFFFF').fontWeight(FontWeight.Bold)Text('createFromBuilder 截图内容').fontSize(12).fontColor('#CCFFCC')Row({space:6}){Circle({width:20,height:20}).fill('#FF6B6B')Circle({width:20,height:20}).fill('#4ECDC4')Circle({width:20,height:20}).fill('#FFE66D')}}.width(260).height(100).backgroundColor('#2C3E50').borderRadius(12).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}

createFromBuilder vs get(),怎么选?

场景推荐方法
截取屏幕上已有的组件get(id)
动态生成不需要显示的图片createFromBuilder
生成分享海报、卡片图createFromBuilder
截取当前页面某个区域get(id)

写在最后

createFromBuilder是生成动态图片的利器,特别适合"分享给朋友"这种功能——生成一张带用户数据的卡片图,直接分享,不需要专门做一个页面让用户看。

掌握这个方法,很多"截图生成"需求都能轻松搞定。

http://www.cnnetsun.cn/news/2663780.html

相关文章:

  • 掌握MuPDF mutool:命令行PDF处理工具的终极指南
  • 金融行业AI工具选型避坑指南:92%的银行踩过的7个配置陷阱及实时修复方案
  • TeleChat-7B-ms商业落地完全指南:许可协议解读与商用申请流程详解
  • 深入理解nanoT5-base-65kBPE-v2的SiLU/gated-SiLU激活函数机制:提升语言模型性能的终极指南
  • 树莓派Pico与BMP180传感器:从I2C通信到微型气象站搭建实践
  • 开发者必看:SenseNova-SI-1.4-InternVL3-8B核心代码解析之InternVisionModel实现原理
  • Veo多场景视频生成性能瓶颈全拆解(GPU显存占用骤降67%的7个底层优化点)
  • AI时代最值钱的能力,不是会写Prompt,而是会验证真相
  • 【车辆SLAM】Rao-Blackwellized粒子滤波器两辆自动驾驶车辆的协作SLAM(距离承载、仅方位、数据关联 全EKF SLAM配合传感器融合策略)【含Matlab源码 1
  • CatPPT:革命性7B开源语言模型,Open LLM Leaderboard排名第一的完全指南
  • 无代码RGB控制器:用电位器手动调光,理解模拟电路与色彩混合
  • Lindy自动化不是工具选型,而是数据生命周期重构:20年架构师首次公开4层抽象模型
  • 基于NE555与光敏电阻的光控机器人小车:模拟电路实现智能避障与寻光
  • 如何将网站设计快速导入Figma进行编辑?HTML To Figma工具完整指南
  • APKMirror:安卓应用获取的终极安全解决方案
  • 如何微调Blenderbot_small-90M:定制你的专属行业聊天机器人
  • 如何快速部署Qwen2.5-14B-Instruct-GPTQ-Int8:5分钟上手教程
  • 如何用可视化编程在3周内从零开发出你的第一个移动应用?
  • 红米K50 Ultra连不上小米平板5?MIUI 14.0.7与Win11双系统下的妙享中心避坑指南
  • 工业云脑: 10 网络安全:零信任与IEC 62443
  • 如何完全掌控你的无人机固件:DankDroneDownloader终极指南
  • 5个简单步骤,用OpenSPG快速构建你的第一个企业级知识图谱
  • LibreCAD:从零开始的免费2D CAD设计之旅 [特殊字符]
  • Ryzen SDT调试工具:免费解锁AMD处理器的终极性能调谐指南
  • 3大高效IDM激活技巧:注册表锁定技术完整解析
  • 3分钟掌握PicQuickCompare:终极图片差异检测工具完全指南
  • 今天不优化Gemini报告生成流程,明天就掉出AIGC应用第一梯队——2024 Q2全球头部科技公司落地速率对比报告
  • Win10下Cadence SPB17.4中文UI显示不全?别只怪分辨率,DPI设置和补丁版本(S032)才是关键
  • 从LPC到eSPI:一文看懂PC硬件“慢速总线”的演进与选型指南
  • 智能简历投递自动化工具:3步实现多平台高效求职的完整指南