如何实现输入框实时改变二维码并支持截图展示
=====================

#### 问题现象

期望实现根据输入框内容，实时生成二维码，并且支持点击按钮进行截图展示。

#### 背景知识

*   [二维码生成](https://developer.huawei.com/consumer/cn/doc/design-guides/qrcode-0000001929816020)：将链接或文案转换生成为二维码的样式来展示。
*   [双向绑定](https://developer.huawei.com/consumer/cn/doc/atomic-ascf/logical-layer-event-bidirectional-binding)：支持将用户输入实时同步给service层对应的字段值。状态管理V2可以使用[!!语法](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-binding)完成双向绑定。
*   [组件截图](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-uicontext-component-snapshot)：将应用内一个组件节点树的渲染结果生成位图（[PixelMap](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-image-pixelmap)）的能力。

#### 解决方案

*   实现思路：
    *   通过componentSnapshot.getSync()方法截取二维码组件图像。
        
        Button("点击生成截图")
          .onClick(() \=\> {
            try {
              this.hideInputMethod();
              let pixelmap \= componentSnapshot.getSync("qr\_id", { scale: 0.5, waitUntilRenderFinished: true });
              this.pixmap \= pixelmap;
            } catch (error) {
              console.error("getSync errorCode: " \+ error.code \+ " message: " \+ error.message);
            }
          }).margin(10);
        
    *   通过TextArea实现文本输入，并使用!!语法实现文本输入的实时双向绑定。
    *   通过QRCode组件实现二维码生成。
        
        TextArea({ text: this.normalQrTxt!! }).fontSize(9).width("50%").fontSize(15).height(140);
        QRCode(this.normalQrTxt).width(140).height(140);
        
*   完整代码如下：
    
    import { componentSnapshot } from "@kit.ArkUI";
    import { image } from "@kit.ImageKit";
    import { inputMethod } from "@kit.IMEKit";
    
    @Entry
    @ComponentV2
    struct Index {
      @Local pixmap: image.PixelMap | undefined \= undefined;
      @Local normalQrTxt: string \= "普通二维码文案";
    
      build() {
        Column() {
          Row() {
            Image(this.pixmap)
              .width("50%")
              .border({ color: Color.Black, width: 2 })
              .height(140)
              .objectFit(ImageFit.Contain);
          };
    
          Button("点击生成截图")
            .onClick(() \=\> {
              try {
                this.hideInputMethod();
                let pixelmap \= componentSnapshot.getSync("qr\_id", { scale: 0.5, waitUntilRenderFinished: true });
                this.pixmap \= pixelmap;
              } catch (error) {
                console.error("getSync errorCode: " \+ error.code \+ " message: " \+ error.message);
              }
            }).margin(10);
    
          Button("点击清空截图")
            .onClick(() \=\> {
              this.hideInputMethod();
              this.pixmap \= image.createPixelMapSync({ size: { width: 100, height: 100 } });
            });
    
          Column({ space: 25 }) {
            Row({ space: 15 }) {
              TextArea({ text: this.normalQrTxt!! }).fontSize(9).width("50%").fontSize(15).height(140);
              QRCode(this.normalQrTxt).width(140).height(140);
            };
          }.width("100%").margin({ top: 25 }).id("qr\_id");
        }
        .onClick(() \=\> {
          this.hideInputMethod();
        })
        .width("100%")
        .height("70%")
        .justifyContent(FlexAlign.Center)
        .alignItems(HorizontalAlign.Center);
      }
    
      private hideInputMethod() {
        try {
          inputMethod.getController().hideTextInput().catch(() \=\> {
            console.error("hideTextInput occur error");
          });
        } catch (error) {
          console.error("get inputMethod controller occur error");
        }
      }
    }