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 自定义弹窗显示效果
ICP备案:
公安联网备案: