ArkUI CustomDialog自定义弹窗的用法(附带实例)
CustomDialog 是自定义弹窗组件,可用于广告、中奖、警告、软件更新等与用户交互响应的操作。开发者可以通过 CustomDialogController 类来显示自定义弹窗。
当前,ArkUI 的弹窗均为非页面级弹窗。在页面路由跳转时,如果开发者未调用 close 方法将其关闭,弹窗将不会自动关闭。若需实现在跳转页面时覆盖弹窗,建议使用 Navigation。
由于 CustomDialogController 在使用上存在诸多限制(例如不支持动态创建和刷新),因此在相对复杂的应用场景中,推荐使用从 UIContext 中获取的 PromptAction 对象提供的 openCustomDialog 接口来实现自定义弹窗。
关闭弹窗之后,若需要释放对应的 ComponentContent,则需要调用 ComponentContent 的 dispose 方法。
因此,若需要更新弹窗中自定义组件的内容,可以通过 ComponentContent 提供的 update 方法来实现:
自定义弹窗组件的完整示例代码如下:
1) PromptAction.ets:
2) Demo.ets:

图 1 自定义弹窗显示效果
当前,ArkUI 的弹窗均为非页面级弹窗。在页面路由跳转时,如果开发者未调用 close 方法将其关闭,弹窗将不会自动关闭。若需实现在跳转页面时覆盖弹窗,建议使用 Navigation。
由于 CustomDialogController 在使用上存在诸多限制(例如不支持动态创建和刷新),因此在相对复杂的应用场景中,推荐使用从 UIContext 中获取的 PromptAction 对象提供的 openCustomDialog 接口来实现自定义弹窗。
自定义弹窗的打开与关闭
1) 创建ComponentContent
ComponentContent 用于定义自定义弹窗的内容:private contentNode: ComponentContent<Object> = new ComponentContent( this.ctx, wrapBuilder(buildText), new Params(this.message) );其中,wrapBuilder(buildText) 封装了自定义组件;new Params(this.message)是自定义组件的入参,可以省略,也可以传入基础数据类型。
2) 打开自定义弹窗
通过调用 openCustomDialog 接口打开的弹窗默认为 customStyle 为 true 的弹窗,即弹窗内容的样式完全按照 contentNode 自定义样式显示。this.ctx.getPromptAction().openCustomDialog(this.contentNode, this.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}`); })
3) 关闭自定义弹窗
由于 closeCustomDialog 接口需要传入待关闭的弹窗对应的 ComponentContent,因此,如果需要在弹窗中设置关闭方法,则可通过封装静态方法来实现。关闭弹窗之后,若需要释放对应的 ComponentContent,则需要调用 ComponentContent 的 dispose 方法。
this.ctx.getPromptAction().closeCustomDialog(this.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}`); })
更新自定义弹窗
1) 更新自定义弹窗的内容
ComponentContent 与 BuilderNode 使用上有相同的限制,不支持自定义组件使用 @Reusable、@Link、@Provide、@Consume 等装饰器来同步弹窗弹出的页面与 ComponentContent 中自定义组件的状态。因此,若需要更新弹窗中自定义组件的内容,可以通过 ComponentContent 提供的 update 方法来实现:
this.contentNode.update(new Params('update'))
2) 更新自定义弹窗的属性
通过 updateCustomDialog 可以动态更新弹窗的属性。目前支持的属性包括 alignment、offset、autoCancel、maskColor。this.ctx.getPromptAction().updateCustomDialog(this.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}`); })需要注意的是,在更新属性时,未设置的属性会恢复为默认值。例如,初始设置 { alignment:DialogAlignment.Top, offset: { dx: 0, dy: 50 } },更新时设置 { alignment: DialogAlignment.Bottom },则初始设置的 offset: { dx: 0, dy: 50 } 不会保留,而会恢复为默认值。
自定义弹窗组件的完整示例代码如下:
1) PromptAction.ets:
import { BusinessError } from '@kit.BasicServicesKit'; import { ComponentContent, window } from '@kit.ArkUI'; import { UIContext } from '@ohos.arkui.UIContext'; export class PromptAction { // UI上下文 static ctx: UIContext; // 内容节点 static contentNode: ComponentContent<Object>; // 弹窗选项 static options: Object; static setContext(context: UIContext) { PromptAction.ctx = context; } static setContentNode(node: ComponentContent<Object>) { PromptAction.contentNode = node; } static setOptions(options: Object) { PromptAction.options = options; } static openDialog() { // 如果存在内容节点,则打开自定义弹窗 if (PromptAction.contentNode !== null) { PromptAction.ctx .getPromptAction() .openCustomDialog(PromptAction.contentNode, PromptAction.options) .then(() => { console.info('openCustomDialog complete.'); }) .catch((error: BusinessError) => { const message = (error as BusinessError).message; const code = (error as BusinessError).code; console.error(`openCustomDialog args error code is ${code}, message is ${message}`); }); } } static closeDialog() { // 关闭自定义弹窗 if (PromptAction.contentNode !== null) { PromptAction.ctx .getPromptAction() .closeCustomDialog(PromptAction.contentNode) .then(() => { console.info('closeCustomDialog complete.'); }) .catch((error: BusinessError) => { const message = (error as BusinessError).message; const code = (error as BusinessError).code; console.error(`closeCustomDialog args error code is ${code}, message is ${message}`); }); } } static updateDialog(options: Object) { // 更新自定义弹窗选项 if (PromptAction.contentNode !== null) { PromptAction.ctx .getPromptAction() .updateCustomDialog(PromptAction.contentNode, options) .then(() => { console.info('updateCustomDialog complete.'); }) .catch((error: BusinessError) => { const message = (error as BusinessError).message; const code = (error as BusinessError).code; console.error(`updateCustomDialog args error code is ${code}, message is ${message}`); }); } } }
2) Demo.ets:
import { ComponentContent, promptAction } from '@kit.ArkUI'; import { PromptAction } from './PromptAction'; // 声明类,用于封装弹窗要显示的文本 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(() => { PromptAction.closeDialog(); }) .backgroundColor('#FFF0F0F0'); } } @Entry @Component struct PromptSample { @State message: string = 'hello'; private ctx: UIContext = this.getUIContext(); // 创建组件内容实例,包括了当前UI上下文,调用了组件构造器,传递了显示的内容 private contentNode: ComponentContent<Object> = new ComponentContent(this.ctx, wrapBuilder(buildText), new Params(this.message)); // 在页面出现之前,设置弹窗的上下文、内容节点和选项 aboutToAppear(): void { PromptAction.setContext(this.ctx); PromptAction.setContentNode(this.contentNode); // 对齐方式为顶部对齐,偏移量垂直下拉50vp PromptAction.setOptions({ alignment: DialogAlignment.Top, offset: { dx: 0, dy: 50 } } as promptAction.BaseDialogOptions); } build() { Row() { Column() { Button('打开弹窗并更新选项') .margin({ top: 50 }) .onClick(() => { PromptAction.openDialog(); // 1500ms后修改弹窗的配置信息 setTimeout(() => { // 更新弹窗的选项 PromptAction.updateDialog({ // 底部显示 alignment: DialogAlignment.Bottom, // 偏移量 offset: { dx: 0, dy: -50 } } as promptAction.BaseDialogOptions); }, 1500); // 1.5s之后更改 }); Button('打开弹窗并更新内容') .margin({ top: 50 }) .onClick(() => { // 打开弹窗 PromptAction.openDialog(); // 1500ms后,更新显示的内容 setTimeout(() => { this.contentNode.update(new Params('update')); }, 1500); }); } .width('100%') .height('100%'); } .height('100%'); } }显示效果如下图所示:

图 1 自定义弹窗显示效果