如何封装Popup组件到SDK
===============

#### 问题现象

如何将Popup组件封装到har包中，以便在项目中统一使用。

#### 背景知识

*   [Popup](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-popup-and-menu-components-popup)：Popup属性可绑定在组件上显示气泡弹窗提示，设置弹窗内容、交互逻辑和显示状态。主要用于屏幕录制、信息弹出提醒等显示状态。
*   [openPopup](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-promptaction#openpopup18)：创建并弹出以content作为内容的Popup弹窗，使用该接口时，若未传入有效的target，则无法弹出Popup弹窗。
*   [TargetInfo](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-i#targetinfo18)：指定组件绑定的目标节点。

#### 解决方案

可以使用[openPopup](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-promptaction#openpopup18)方法为指定组件弹出气泡。示例代码如下：

1.  har包封装：
    
    import { BusinessError } from '@kit.BasicServicesKit';
    import { ComponentContent, TargetInfo, PromptAction } from '@kit.ArkUI';
    
    
    export class PromptActionClass {
      private promptAction: PromptAction | null = null;
      private contentNode: ComponentContent<Object> | null = null; _// popup弹框组件内容_
      private options: PopupCommonOptions | null = null;
      private target: TargetInfo | null = null; _// 目标组件信息_
      private isPartialUpdate: boolean = false;
    
    
      public setPromptAction(promptAction: PromptAction) {
        this.promptAction = promptAction;
      }
    
    
      public setContentNode(node: ComponentContent<Object>) {
        this.contentNode = node;
      }
    
    
      public setTarget(target: TargetInfo) {
        this.target = target;
      }
    
    
      public setOptions(options: PopupCommonOptions) {
        this.options = options;
      }
    
    
      public setIsPartialUpdate(isPartialUpdate: boolean) {
        this.isPartialUpdate = isPartialUpdate;
      }
    
    
     _ // 打开popup_
      public openPopup() {
        if (this.promptAction != null) {
          this.promptAction.openPopup(this.contentNode, this.target, this.options)
            .then(() => {
              console.info(\`openPopup success\`);
            })
            .catch((err: BusinessError) => {
              console.error(\`openPopup error: ${err.code}  ${err.message}\`);
            });
        }
      }
    
    
      _// 关闭popup_
      public closePopup() {
        if (this.promptAction != null) {
          this.promptAction.closePopup(this.contentNode)
            .then(() => {
              console.info(\`closePopup success\`);
            })
            .catch((err: BusinessError) => {
              console.error(\`closePopup error:  ${err.code}  ${err.message}\`);
            });
        }
      }
    
    
     _ // 更新popup_
      public updatePopup(options: PopupCommonOptions) {
        if (this.promptAction != null) {
          this.promptAction.updatePopup(this.contentNode, options, this.isPartialUpdate)
            .then(() => {
              console.info(\`updatePopup success\`);
            })
            .catch((err: BusinessError) => {
              console.error(\`updatePopup error:  ${err.code}  ${err.message}\`);
            });
        }
      }
    }
    
2.  在entry包的oh-package.json5中声明har包：
    
    "dependencies": {
      "custompopupsdk": 'file:../CustomPopupSDK'
    },
    
3.  entry包使用：
    
    import { PromptActionClass } from 'custompopupsdk';
    import { ComponentContent, PromptAction } from '@kit.ArkUI';
    
    _// 用于传递参数_
    class Params {
      title: string = '';
      text: string = '';
      promptActionClass: PromptActionClass = new PromptActionClass();
      ;
    
    
      constructor(title: string, text: string, promptActionClass: PromptActionClass) {
        this.title = title;
        this.text = text;
        this.promptActionClass = promptActionClass;
      }
    }
    
    _// popup内容_
    @Builder
    function buildText(params: Params) {
      Row() {
        Column() {
          Image($rawfile('logo.png'))
            .width(32)
            .height(32)
            .borderRadius(8)
        }
        .width(32)
        .height(90)
    
    
        Column() {
          Column({ space: 2 }) {
            Row() {
              Text(params.title)
                .fontSize(16)
                .fontColor('#000000')
                .fontWeight(500)
                .lineHeight(22)
                .width(214)
    
    
              Image($rawfile('xmark.svg')).width(18).height(18)
                .onClick(() => {
                 _ // 关闭popup_
                  params.promptActionClass.closePopup();
                })
                .margin({
                  left: 12
                })
            }
            .width('100%')
            .height(22)
    
    
            Text(params.text)
              .fontSize(14)
              .fontWeight(400)
              .lineHeight(19)
              .width('100%')
              .maxLines(2)
              .textOverflow({ overflow: TextOverflow.Ellipsis })
          }
          .justifyContent(FlexAlign.Start)
          .width('100%')
          .height(62)
    
    
    
    
          Row() {
            Text('Update')
              .fontSize(14)
              .fontColor('#0A59F7')
              .fontWeight(500)
              .lineHeight(19)
              .onClick(() => {
               _ // 更新popup内容样式_
                params.promptActionClass.updatePopup({
                  enableArrow: false,
                });
              })
          }
          .width(244)
          .height(20)
          .margin({
            top: 8
          })
        }
        .margin({
          left: 12
        })
        .width(244)
        .height(90)
        .alignItems(HorizontalAlign.Start)
        .justifyContent(FlexAlign.Start)
    
    
      }.justifyContent(FlexAlign.Center)
      .width(312)
      .height(114)
      .borderRadius(20)
    }
    
    
    @Entry
    @Component
    struct Index {
      @State title: string = 'Title';
      @State text: string =
        'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
      private uiContext: UIContext = this.getUIContext();
      private promptAction: PromptAction = this.uiContext.getPromptAction();
      private promptActionClass: PromptActionClass = new PromptActionClass();
      private targetId: string | number = 0; _// 目标组件id_
      private contentNode: ComponentContent<Object> =
        new ComponentContent(this.uiContext, wrapBuilder(buildText),
          new Params(this.title, this.text, this.promptActionClass)); _// 初始化自定义popup组件_
      private options: PopupCommonOptions = { enableArrow: true, autoCancel: false };
    
    
      build() {
        Column() {
          Column() {
            Text('文本一')
            Text('给文本三加气泡')
              .fontColor('#0A59F7')
              .onClick(() => {
               _ // 指定弹出组件ID_
                let targetId = 'column3';
                if (targetId == undefined) {
                  this.targetId = 0;
                } else {
                  this.targetId = targetId;
                }
                this.promptActionClass.setPromptAction(this.promptAction);
                this.promptActionClass.setContentNode(this.contentNode);
                this.promptActionClass.setOptions(this.options);
                this.promptActionClass.setIsPartialUpdate(false);
                this.promptActionClass.setTarget({ id: this.targetId });
            _    // 打开popup_
                this.promptActionClass.openPopup();
              })
          }
          .width('100%')
          .height(100)
          .backgroundColor('#F1F3F5')
          .borderRadius(20)
          .id('column1')
          .margin({
            top: 10
          })
          .padding({
            top: 15,
            bottom: 15
          })
          .justifyContent(FlexAlign.SpaceEvenly)
    
    
          Column() {
            Text('文本二')
            Text('给文本二加气泡')
              .fontColor('#0A59F7')
              .onClick(() => {
            _    // 指定组件ID_
                let targetId = 'column2';
                if (targetId == undefined) {
                  this.targetId = 0;
                } else {
                  this.targetId = targetId;
                }
                this.promptActionClass.setPromptAction(this.promptAction);
                this.promptActionClass.setContentNode(this.contentNode);
                this.promptActionClass.setOptions(this.options);
                this.promptActionClass.setIsPartialUpdate(false);
                this.promptActionClass.setTarget({ id: this.targetId });
                this.promptActionClass.openPopup();
              })
          }
          .width('100%')
          .height(100)
          .backgroundColor('#F1F3F5')
          .borderRadius(20)
          .id('column2')
          .margin({
            top: 10
          })
          .padding({
            top: 15,
            bottom: 15
          })
          .justifyContent(FlexAlign.SpaceEvenly)
    
    
          Column() {
            Text('文本三')
            Text('给文本一加气泡')
              .fontColor('#0A59F7')
              .onClick(() => {
              _  // 指定组件ID_
                let targetId = 'column1';
                if (targetId == undefined) {
                  this.targetId = 0;
                } else {
                  this.targetId = targetId;
                }
                this.promptActionClass.setPromptAction(this.promptAction);
                this.promptActionClass.setContentNode(this.contentNode);
                this.promptActionClass.setOptions(this.options);
                this.promptActionClass.setIsPartialUpdate(false);
                this.promptActionClass.setTarget({ id: this.targetId });
                this.promptActionClass.openPopup();
              })
          }
          .width('100%')
          .height(100)
          .borderRadius(20)
          .backgroundColor('#F1F3F5')
          .id('column3')
          .margin({
            top: 10
          })
          .padding({
            top: 15,
            bottom: 15
          })
          .justifyContent(FlexAlign.SpaceEvenly)
        }
      }
    }
    
    运行效果图如下：
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/77/v3/rt4dDRK1RYSW5vRafu5NIw/zh-cn_image_0000002628592954.png?HW-CC-KV=V1&HW-CC-Date=20260709T133936Z&HW-CC-Expire=86400&HW-CC-Sign=3E012C0EFEB5DCBE87EAC0F948BCE432EAE91D7C886D9E8712337F5064620E64 "点击放大")