ArkTS 5.0之后推荐Dialog创建方式

hm688c7201d1ed8
发布于 2025-10-17 11:34
浏览
0收藏

文档明确写了之前的CustomDialog不推荐,给出了推荐的新的创建方式:地址是:​​不依赖UI组件的全局自定义弹出框 (openCustomDialog)(推荐)​

原文给出的代码是:

// PromptActionClass.ets
import { BusinessError } from '@kit.BasicServicesKit';
import { ComponentContent, promptAction, UIContext } from '@kit.ArkUI';

export class PromptActionClass {
  static ctx: UIContext;
  static contentNode: ComponentContent<Object>;
  static options: promptAction.BaseDialogOptions;

  static setContext(context: UIContext) {
    PromptActionClass.ctx = context;
  }

  static setContentNode(node: ComponentContent<Object>) {
    PromptActionClass.contentNode = node;
  }

  static setOptions(options: promptAction.BaseDialogOptions) {
    PromptActionClass.options = options;
  }

  static openDialog() {
    if (PromptActionClass.contentNode !== null) {
      PromptActionClass.ctx.getPromptAction().openCustomDialog(PromptActionClass.contentNode, PromptActionClass.options)
        .then(() => {
          console.info('OpenCustomDialog complete.');
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`OpenCustomDialog args error code is ${code}, message is ${message}`);
        })
    }
  }

  static closeDialog() {
    if (PromptActionClass.contentNode !== null) {
      PromptActionClass.ctx.getPromptAction().closeCustomDialog(PromptActionClass.contentNode)
        .then(() => {
          console.info('CloseCustomDialog complete.');
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`CloseCustomDialog args error code is ${code}, message is ${message}`);
        })
    }
  }

  static updateDialog(options: promptAction.BaseDialogOptions) {
    if (PromptActionClass.contentNode !== null) {
      PromptActionClass.ctx.getPromptAction().updateCustomDialog(PromptActionClass.contentNode, options)
        .then(() => {
          console.info('UpdateCustomDialog complete.');
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`UpdateCustomDialog args error code is ${code}, message is ${message}`);
        })
    }
  }
}

// Index.ets
import { ComponentContent } from '@kit.ArkUI';
import { PromptActionClass } from './PromptActionClass';

class Params {
  text: string = "";

  constructor(text: string) {
    this.text = text;
  }
}

@Builder
function buildText(params: Params) {
  Column() {
    Text(params.text)
      .fontSize(50)
      .fontWeight(FontWeight.Bold)
      .margin({ bottom: 36 })
    Button('Close')
      .onClick(() => {
        PromptActionClass.closeDialog();
      })
  }.backgroundColor('#FFF0F0F0')
}

@Entry
@Component
struct Index {
  @State message: string = "hello";
  private ctx: UIContext = this.getUIContext();
  private contentNode: ComponentContent<Object> =
    new ComponentContent(this.ctx, wrapBuilder(buildText), new Params(this.message));

  aboutToAppear(): void {
    PromptActionClass.setContext(this.ctx);
    PromptActionClass.setContentNode(this.contentNode);
    PromptActionClass.setOptions({ alignment: DialogAlignment.Top, offset: { dx: 0, dy: 50 } });
  }

  build() {
    Row() {
      Column() {
        Button("open dialog and update options")
          .margin({ top: 50 })
          .onClick(() => {
            PromptActionClass.openDialog();

            setTimeout(() => {
              PromptActionClass.updateDialog({
                alignment: DialogAlignment.Bottom,
                offset: { dx: 0, dy: -50 }
              });
            }, 1500)
          })
        Button("open dialog and update content")
          .margin({ top: 50 })
          .onClick(() => {
            PromptActionClass.openDialog();

            setTimeout(() => {
              this.contentNode.update(new Params('update'));
            }, 1500)
          })
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
  }
}

使用起来特别不方便,因此需要把它抽出成方法:

//TestDialog.ets
import { BusinessError } from '@kit.BasicServicesKit';
import { ComponentContent, promptAction, UIContext } from '@kit.ArkUI';

/**
 * 自定义弹窗(类似 Android Dialog 封装)
 * 用法:
 *   const dialog = new CustomDialog(this.getUIContext())
 *   dialog.setMessage("加载中...").show()
 *   dialog.dismiss()
 */
export class TestDialog {
    private ctx: UIContext;
    private contentNode: ComponentContent<Object>;
    private options: promptAction.BaseDialogOptions;
    private params: DialogParams;

    constructor(ctx: UIContext) {
        this.ctx = ctx;
        this.params = new DialogParams('', () => this.dismiss()); // 初始空文本
        this.contentNode = new ComponentContent(
            this.ctx,
            wrapBuilder(buildDialogContent),
            this.params
        );
        this.options = {
            alignment: DialogAlignment.Center,
            offset: { dx: 0, dy: 0 }
        };
    }

    /** 设置显示内容 */
    setMessage(msg: string): TestDialog {
        this.params.text = msg;
        this.contentNode.update(this.params);
        return this;
    }

    /** 打开弹窗 */
    show(): void {
        this.ctx.getPromptAction()
            .openCustomDialog(this.contentNode, this.options)
            .then(() => console.info('Dialog opened.'))
            .catch((error: BusinessError) => {
                console.error(`OpenCustomDialog error: ${error.code}, ${error.message}`);
            });
    }

    /** 关闭弹窗 */
    dismiss(): void {
        this.ctx.getPromptAction()
            .closeCustomDialog(this.contentNode)
            .then(() => console.info('Dialog closed.'))
            .catch((error: BusinessError) => {
                console.error(`CloseCustomDialog error: ${error.code}, ${error.message}`);
            });
    }

    /** 更新弹窗配置 */
    updateOptions(options: promptAction.BaseDialogOptions): TestDialog {
        // ✅ ArkTS 不允许使用 Object.assign,手动合并
        let newOptions: promptAction.BaseDialogOptions = {
            alignment: this.options.alignment,
            offset: this.options.offset
        };

        if (options.alignment !== undefined) {
            newOptions.alignment = options.alignment;
        }
        if (options.offset !== undefined) {
            newOptions.offset = options.offset;
        }

        this.options = newOptions;

        this.ctx.getPromptAction()
            .updateCustomDialog(this.contentNode, this.options)
            .then(() => console.info('Dialog options updated.'))
            .catch((error: BusinessError) => {
                console.error(`UpdateCustomDialog error: ${error.code}, ${error.message}`);
            });
        return this;
    }
}

/** 弹窗参数对象 */
class DialogParams {
    text: string = '';
    onClose: () => void;
    constructor(text: string, onClose: () => void) {
        this.text = text;
        this.onClose = onClose;
    }
}

/** 弹窗内部 UI */
@Builder
function buildDialogContent(params: DialogParams) {
    Column() {
        Text(params.text)
            .fontSize(20)
            .fontWeight(FontWeight.Medium)
            .margin({ bottom: 20 })
        Button('关闭')
            .backgroundColor('#007DFF')
            .fontColor('#FFFFFF')
            .onClick(() => {
                // ✅ 直接调用外层传入的关闭函数
                params.onClose();
            })
    }
    .padding(20)
    .backgroundColor('#FFFFFFFF')
    .borderRadius(12)
    .shadow({ radius: 10, color: '#22000000' })
}

分类
标签
收藏
回复
举报
回复
    相关推荐