1、前 言
我们在鸿蒙UI系统组件08------自定义弹窗(CustomDialog)文章中介绍到,我们可以通过CustomDialogController类显示自定义弹窗。
由于CustomDialogController在使用上存在诸多限制,例如:不支持动态创建、不支持动态刷新。
在相对较复杂的应用场景中我们使用UIContext中获取到的PromptAction对象提供的openCustomDialog接口来实现自定义弹窗。下面针对openCustomDialog的使用做一个简单介绍。
2、弹出自定义弹窗
在使用弹窗前,我们需要创建ComponentContent对象,ComponentContent用于定义自定义弹窗的内容。创建一个ComponentContent对象的实例代码如下(核心代码 23 ~ 24行):
import { ComponentContent } from '@kit.ArkUI';// 自定义弹窗的Builder函数(构建弹窗的内容)@Builderfunction buildText(params: Params) { Column() { Text(params.text) .fontSize(50) .fontWeight(FontWeight.Bold) .margin({ bottom: 36 }) Button('Close') .onClick(() => { PromptActionClass.closeDialog() }) }.backgroundColor('#FFF0F0F0')}@Entry@Componentstruct Index { @State message: string = "鸿蒙自习室" private ctx: UIContext = this.getUIContext(); private contentNode: ComponentContent<Object> = new ComponentContent(this.ctx, wrapBuilder(buildText), new Params(this.message)); build() { // ... }}
其中,wrapBuilder(buildText)封装自定义组件,new Params(this.message)是自定义组件的入参,可以缺省,也可以传入基础数据类型。
通过调用openCustomDialog接口打开弹窗。代码如下:
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的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}`); })
4、更新自定义弹窗的内容
ComponentContent与BuilderNode有相同的使用限制,不支持自定义组件使用@Reusable、@Link、@Provide、@Consume等装饰器,来同步弹窗弹出的页面与ComponentContent中自定义组件的状态。
因此,若需要更新弹窗中自定义组件的内容可以通过ComponentContent提供的update方法来实现。
this.contentNode.update(new Params('update'))
5、更新自定义弹窗的属性
通过updateCustomDialog可以动态更新弹窗的属性。目前支持的属性包括alignment、offset、autoCancel、maskColor。
需要注意的是,更新属性时,未设置的属性会恢复为默认值。例如,初始设置{ alignment: DialogAlignment.Top, offset: { dx: 0, dy: 50 } },更新时设置{ alignment: DialogAlignment.Bottom },则初始设置的offset: { dx: 0, dy: 50 }不会保留,会恢复为默认值。
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}`); })
6、一个弹窗示例
示例效果如下:

👉🏻 先封装一个全局通用的工具类PromptActionClass.ts(用于弹窗/关闭弹窗/更新弹窗)
// PromptActionClass.tsimport { BusinessError } from '@kit.BasicServicesKit';import { ComponentContent, promptAction } from '@kit.ArkUI';import { UIContext } from '@ohos.arkui.UIContext';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}`); }) } }}
👉🏻 在界面中需要弹出时,使用PromptActionClass,示例如下:
// Index.etsimport { ComponentContent } from '@kit.ArkUI';import { PromptActionClass } from './PromptActionClass';class Params { text: string = "" constructor(text: string) { this.text = text; }}@Builderfunction buildText(params: Params) { Column() { Text(params.text) .fontSize(50) .fontWeight(FontWeight.Bold) .margin({ bottom: 36 }) Button('Close') .onClick(() => { PromptActionClass.closeDialog() }) }.backgroundColor('#FFF0F0F0')}@Entry@Componentstruct Index { @State message: string = "鸿蒙自习室" 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("弹出对话框后,1.5秒更新位置") .margin({ top: 50 }) .onClick(() => { this.message = '鸿蒙自习室'; PromptActionClass.openDialog() setTimeout(() => { PromptActionClass.updateDialog({ alignment: DialogAlignment.Bottom, offset: { dx: 0, dy: -50 } }) }, 1500) }) Button("弹出对话框后,1.5秒更新文案") .margin({ top: 50 }) .onClick(() => { PromptActionClass.openDialog() setTimeout(() => { this.contentNode.update(new Params('harmony自习室')) }, 1500) }) } .width('100%') .height('100%') } .height('100%') }}