
回复
文档明确写了之前的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' })
}