DEV Community

HarmonyOS
HarmonyOS

Posted on

How to pass the image obtained after taking a screenshot of a component to other components

Read the original article:How to pass the image obtained after taking a screenshot of a component to other components

Context

How to pass the screenshot of a component to other components for display?

Description

  • Goal: Capture a screenshot of a component (using componentSnapshot.get()) and display it in a custom dialog.
  • Issue: The CustomDialogController is initialized early (with pixMap = undefined). Later updates to pixMap do not propagate to the dialog because the controller’s builder uses stale initial values.
  • Key Methods:
    • componentSnapshot.get(id, options) captures the component as PixelMap.
    • @Link/@Prop decorators are intended for parent-child data synchronization.

Solution / Approach

import { image } from '@kit.ImageKit'
import { componentSnapshot } from '@kit.ArkUI'

@Entry
@Component
struct Index {
  @State items: string[] =
    ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20',
      '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32']
  @State pixMap: image.PixelMap | undefined = undefined
  @State mText: string = 'I am the Content'
  // In the dialogController, I tried passing pixMap, options, and buffer, but it didn't work.
  dialogController: CustomDialogController =
    new CustomDialogController({ builder: CustomDialogComponent({ pixelMap: this.pixMap, text: this.mText }) })

  build() {
    Column() {
      Text('I am the title.')
        .width('100%')
        .height(50)
        .textAlign(TextAlign.Center)
        .fontColor(Color.Black)
        .backgroundColor(Color.Gray)
      Scroll() {
        Column() {
          ForEach(this.items, (item: string) => {
            Text('I am content.' + item).width('100%').height(50).fontColor(Color.Red)
          })
        }.width('100%')
      }.width('100%').layoutWeight(1).id('mainScroll')

      Blank().width('100%').height(1).backgroundColor(Color.Black)
      // This can be used as a comparative test.
      Image(this.pixMap).width('100%').layoutWeight(0.5).objectFit(ImageFit.Contain)

      Button('Click to take a screenshot').width(100).height(45).onClick(() => {
        componentSnapshot.get('mainScroll', { scale: 0.8, waitUntilRenderFinished: true })
          .then((pixMap: image.PixelMap) => {
            // If using the pixMap method directly, just this one line is sufficient, and comparative testing is also possible.
            this.pixMap = pixMap

            this.dialogController.open()

            this.mText = 'Screenshot successful'
          })
          .catch((err: Error) => {
            console.info('Screenshot failed:' + JSON.stringify(err))
          })
      })
    }.width('100%').height('100%').backgroundColor(Color.White)
  }
}
Enter fullscreen mode Exit fullscreen mode

Popup component code:

@CustomDialog
struct CustomDialogComponent {
  controller?: CustomDialogController
  // Using @Prop or @Link here is not feasible without passing the buffer.
  @Link pixelMap: image.PixelMap | undefined /*= undefined*/
  @Prop text: string | undefined

  build() {
    Column() {
      Text(this.text).width('100%').height(50).textAlign(TextAlign.Center).fontColor(Color.Green)
      Image(this.pixelMap).width(100).objectFit(ImageFit.Contain)

      Button('Close')
        .width(100)
        .height(45)
        .backgroundColor('#ffcc0000')
        .onClick(() => {
          this.controller?.close()
        })
        .margin({ top: 10 })
    }.backgroundColor(Color.White)
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaways:

  • The issue in the original code was due to the CustomDialogController being created too early (with initial undefined PixelMap) and not being updated when the PixelMap becomes available.
  • By conditionally rendering the CustomDialog component and using @Prop to pass the PixelMap, we ensure that the dialog is built with the latest captured image.
  • This approach avoids the complexity of managing a CustomDialogController and allows for a more straightforward data flow.

Written by Dogan Evci

Top comments (0)