加入下方官方班级,得鸿蒙礼盒

一起拿鸿蒙礼盒,戳我戳我!!

本期活动时间:2025年8月1日-12月31日


问题现象

使用CustomDialog实现多个弹窗链式调用时,当在第一个弹窗中打开第二个弹窗时,第二个弹窗未能正确显示,实际显示的还是第一个弹窗的内容。

问题代码示例参考如下:

@CustomDialog
struct MyDialog1 {
controller1: CustomDialogController
controller2: CustomDialogController
title: string = ''

build() {
Row() {
Column({ space: 10 }) {
Text(this.title)
.fontSize(30)
.fontColor(Color.Blue)
Button('点击打开弹窗2')
.onClick(() => {
this.controller2.open()
}).backgroundColor(0xffffff).fontColor(Color.Red)
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('cancel')
.onClick(() => {
this.controller1.close()
}).backgroundColor(0xffffff).fontColor(Color.Black)
}.width('100%')
}.width('50%')
}.height('50%')
}
}

// 弹窗组件
@CustomDialog
struct MyDialog2 {
controller: CustomDialogController
title: string = ''

build() {
Row() {
Column({ space: 10 }) {
Text(this.title)
.fontSize(30)
.fontColor(Color.Blue)
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('cancel')
.onClick(() => {
this.controller.close()
}).backgroundColor(0xffffff).fontColor(Color.Black)
Button('confirm')
.onClick(() => {
this.controller.close()
}).backgroundColor(0xffffff).fontColor(Color.Red)
}.width('100%')
}.margin({ bottom: 10 })
}.height('50%')
}
}

@Entry
@Component
struct DialogTest {
@State dialogTitle: string = ''
@State dialogData: string = ''
dialogController2: CustomDialogController = new CustomDialogController({
builder: MyDialog2({
title: '弹窗2',
}),
customStyle: false
})
dialogController1: CustomDialogController = new CustomDialogController({
builder: MyDialog1({
controller2: this.dialogController2,
title: '弹窗1',
}),
customStyle: false
})

build() {
Row() {
Column({ space: 10 }) {
Button('点击打开弹窗1')
.onClick(() => {
this.dialogController1.open()
})
}.width('100%')
}.height('100%')
}
}

问题效果预览:

背景知识

  • HarmonyOS使用CustomDialogController类显示自定义弹窗,可通过open方法显示自定义弹窗内容,close方法关闭显示的自定义弹窗。
  • @ohos.promptAction是用于创建和管理弹窗(如提示、确认、输入框等)的模块,支持用户交互操作,常用于弹出提示信息、确认操作或收集用户输入。

问题定位

CustomDialog的打开与关闭都与CustomDialog的CustomDialogController有关,当多个弹窗链式调用时会存在多个CustomDialogController,会出现上述问题的原因可能是由于使用了错误的CustomDialogController,或未将指向自己的controller置于最后导致打开了错误的弹窗。根据上述错误代码中:

controller1: CustomDialogController
controller2: CustomDialogController

错误的弹窗是由于未将自身的controller放置于其它controller之后。

分析结论

在CustomDialog中传入多个其他的controller,以实现在CustomDialog中打开另一个或另一些CustomDialog,那么此处需要将指向自己的controller放在所有controller的后面。

修改建议

为了正确的实现弹窗的嵌套使用,可以通过以下方式实现:

  • 使用CustomDialog,将被嵌套的弹窗的CustomDialogController放置于上一层弹窗中实现嵌套使用,需要注意的是要将指向自己的controller放在其它所有controller的后面。具体可参考示例:弹出嵌套弹窗
  • 实现弹窗链式调用也可使用UIContext中的getPromptAction获取PromptAction实例,再通过此实例调用方法openCustomDialog,通过builder参数传入不同弹窗页面。
import { PromptAction } from '@kit.ArkUI'

@Entry
@Component
struct Index {
private customDialogComponentId: number = 0
private customDialogComponentTwoId: number = 0
private promptAction: PromptAction = this.getUIContext().getPromptAction()

@Builder
customDialogComponentTwo() {
Column() {
Text('第二个弹窗')
Button('关闭弹窗').onClick((event: ClickEvent) => {
// 记录当前弹窗ID
this.promptAction.closeCustomDialog(this.customDialogComponentTwoId)
})
}
}

@Builder
customDialogComponent() {
Column() {
Text('第一个弹窗').fontSize(30)
Text('打开第二个弹窗')
.onClick(() => {
this.promptAction.openCustomDialog({
builder: () => {
this.customDialogComponentTwo()
}
})
.then((dialogId: number) => {
// 记录当前弹窗ID
this.customDialogComponentTwoId = dialogId
})
})
Row({ space: 50 }) {
Button('关闭弹窗').onClick(() => {
this.promptAction.closeCustomDialog(this.customDialogComponentId)
})
}
}.height(200).padding(5).justifyContent(FlexAlign.SpaceBetween)
}

build() {
Row() {
Column({ space: 20 }) {
Text('打开第一个弹窗')
.fontSize(30)
.onClick(() => {
this.promptAction.openCustomDialog({
builder: () => {
this.customDialogComponent()
},
}).then((dialogId: number) => {
this.customDialogComponentId = dialogId
})
})
}
.width('100%')
}
.height('100%')
}
}

总结

上述两种方案都可实现弹窗链式调用,具体如何选用,可根据下表结合自身需求进行选择。

方式

注意点

优点

CustomDialog

通过CustomDialog实现嵌套弹窗,需要注意将指向自己的controller,放在其它所有controller的后面。

CustomDialog具有更高的自定义控制能力。

promptAction

promptAction实现嵌套弹窗无需注册controller,在使用弹窗时只需要在需要弹出的事件中使用promptAction.openCustomDialog。

promptAction使用更加方便。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐