HarmonyOS 鸿蒙Next中利用组件滚动拼接实现滚动截屏

HarmonyOS 鸿蒙Next中利用组件滚动拼接实现滚动截屏

  1. 工具里面需要UIContext,需要在entrybility里面保存
let uiContext: UIContext | undefined = windowStage.getMainWindowSync().getUIContext(); 
AppStorage.setOrCreate('uiContext', uiContext);
  1. 设置截图组件的id
list_id = 'List_ID'
  1. 滚动截图
/**************begin snap****************/
private context = this.getUIContext().getHostContext() as common.UIAbilityContext;
private scroller: Scroller = new Scroller();
private listComponentWidth: number = 0;
private listComponentHeight: number = 0;
private curYOffset: number = 0;
private scrollHeight: number = 0;
private yOffsetBefore: number = 0;
private isClickStop: boolean= false;
@State isEnableScroll: boolean = true;
@StorageLink('screenWidth') screenWidth: number = 0;
@StorageLink('screenHeight') screenHeight: number = 0;
@State snapPopupPosition: Position = { x: 0, y: 0 };
@State mergedImage: PixelMap | undefined = undefined;
private areaArray: image.PositionArea[] = [];
private scrollYOffsets: number[] = [];

//滚动截图的入口方法
async scrollSnapshot() {
  // The settings list cannot be manually scrolled during the screenshot process
  // to avoid interference with the screenshot
  this.isEnableScroll = false;
  // Saves the current location of the component for recovery
  this.yOffsetBefore = this.curYOffset;
  // Set the prompt pop-up to be centered
  this.snapPopupPosition = PopupUtils.calcPopupCenter(this.screenWidth, this.screenHeight, 100, 200);
  await this.scrollSnapAndMerge();
  // [StartExclude context]
  // Open the prompt pop-up window
  this.isShowPreview = true;
  // Initial variable after stitching
  await this.afterGeneratorImage();
  // [EndExclude context]
  this.isEnableScroll = true;
  this.isClickStop = false;
}

//滚动拼接
async scrollSnapAndMerge() {
  // Record an array of scrolls
  this.scrollYOffsets.push(this.curYOffset - this.yOffsetBefore);
  // Call the API for taking screenshots to obtain the current screenshots
  const pixelMap = await this.getUIContext().getComponentSnapshot().get(this.LIST_ID);
  // Gets the number of bytes per line of image pixels.
  let area: image.PositionArea =
    await ImageUtils.getSnapshotArea(pixelMap, this.scrollYOffsets, this.listComponentWidth, this.listComponentHeight)
  this.areaArray.push(area);

  // During the loop, it is determined whether the bottom is reached, and the user does not stop taking screenshots
  if (!this.scroller.isAtEnd() && !this.isClickStop) {
    // Scroll to the next page without scrolling to the end
    CommonUtils.scrollAnimation(this.scroller, 1000, this.scrollHeight);
    await CommonUtils.sleep(1500);
    await this.scrollSnapAndMerge();
  } else {
    // After scrolling to the bottom, the buffer obtained by each round of scrolling is spliced
    // to generate a long screenshot
    this.mergedImage =
      await ImageUtils.mergeImage(this.areaArray, this.scrollYOffsets[this.scrollYOffsets.length - 1],
        this.listComponentWidth, this.listComponentHeight);
  }
}

//完成拼接
async afterGeneratorImage() {
  // Delay for transition animation
  await CommonUtils.sleep(200);
  this.snapPopupPosition = PopupUtils.calcPopupBottomLeft(this.screenHeight, 200);
  this.componentMaskImage = undefined;
  this.scrollYOffsets.length = 0;
  this.areaArray.length = 0;

}
/**************end snap****************/

更多关于HarmonyOS 鸿蒙Next中利用组件滚动拼接实现滚动截屏的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS NEXT中,可通过ScrollView组件嵌套内容组件实现滚动截屏。使用ScrollView的scrollBy方法控制滚动位移,结合PixelMap.createFromSurface获取每帧图像。利用Image.Packer将多帧图像拼接为长图。关键代码:

// 创建ScrollView
let scrollView = new ScrollView();
// 设置滚动回调
scrollView.onScroll(() => {
  // 截取当前帧
  let pixelMap = pixelMapCreator.createPixelMap();
  // 拼接图像
  imagePacker.addImage(pixelMap);
});
// 触发滚动
scrollView.scrollBy(0, offset);

需在config.json中声明"ohos.permission.CAPTURE_SCREEN"权限。

更多关于HarmonyOS 鸿蒙Next中利用组件滚动拼接实现滚动截屏的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个很好的HarmonyOS Next滚动截屏实现方案。我来分析下关键点:

  1. 核心实现思路是通过Scroller组件控制滚动,在每次滚动后调用getComponentSnapshot()获取当前屏幕截图,最后使用mergeImage()拼接成长图。

  2. 几个关键步骤:

  • 初始化时获取UIContext和组件尺寸
  • scrollSnapshot()作为入口方法,禁用手动滚动
  • scrollSnapAndMerge()递归实现滚动和截图
  • 使用PositionArea记录每张截图的位置信息
  • 滚动到底部或用户停止时进行图片拼接
  1. 需要注意的细节:
  • 滚动过程中需要禁止用户交互(isEnableScroll)
  • 要记录滚动偏移量(scrollYOffsets)
  • 适当添加延时保证滚动和截图完成
  • 完成后重置状态变量

这个方案实现了完整的滚动截屏流程,代码结构清晰,通过递归调用实现了自动滚动和截图。对于需要长截图的场景很有参考价值。

回到顶部