問題現象
CustomDialogを使用して複数のダイアログを連続的に表示する際、最初のダイアログから2番目のダイアログを開こうとすると、2番目のダイアログが正しく表示されず、最初のダイアログの内容が表示されてしまいます。
問題のコード例
@CustomDialog
struct FirstDialog {
firstController: CustomDialogController
secondController: CustomDialogController
dialogTitle: string = ''
build() {
Row() {
Column({ space: 15 }) {
Text(this.dialogTitle)
.fontSize(28)
.fontColor(Color.Blue)
Button('次のダイアログを開く')
.onClick(() => {
this.secondController.open()
})
.backgroundColor(Color.White)
.fontColor(Color.Red)
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('キャンセル')
.onClick(() => {
this.firstController.close()
})
.backgroundColor(Color.White)
.fontColor(Color.Black)
}
.width('100%')
}
.width('60%')
}
.height('60%')
}
}
@CustomDialog
struct SecondDialog {
dialogController: CustomDialogController
message: string = ''
build() {
Row() {
Column({ space: 12 }) {
Text(this.message)
.fontSize(26)
.fontColor(Color.Green)
Flex({ justifyContent: FlexAlign.SpaceEvenly }) {
Button('閉じる')
.onClick(() => {
this.dialogController.close()
})
.backgroundColor(Color.White)
.fontColor(Color.Blue)
Button('確認')
.onClick(() => {
this.dialogController.close()
})
.backgroundColor(Color.White)
.fontColor(Color.Red)
}
.width('100%')
}
.margin({ bottom: 15 })
}
.height('50%')
}
}
@Entry
@Component
struct DialogDemo {
@State title: string = ''
@State content: string = ''
secondDialogController: CustomDialogController = new CustomDialogController({
builder: SecondDialog({
message: '2番目のダイアログ',
}),
customStyle: false
})
firstDialogController: CustomDialogController = new CustomDialogController({
builder: FirstDialog({
secondController: this.secondDialogController,
dialogTitle: '最初のダイアログ',
}),
customStyle: false
})
build() {
Row() {
Column({ space: 12 }) {
Button('最初のダイアログを開く')
.onClick(() => {
this.firstDialogController.open()
})
}
.width('100%')
}
.height('100%')
}
}
背景知識
- HarmonyOSでは、CustomDialogControllerクラスを使用してカスタムダイアログを表示します。openメソッドでダイアログを表示し、closeメソッドで閉じます。
- @ohos.promptActionモジュールは、ダイアログ(通知、確認、入力フィールドなど)の作成と管理に使用され、ユーザーとの対話操作をサポートします。
問題の特定
CustomDialogの表示と非表示はCustomDialogControllerに関連しています。複数のダイアログを連続的に呼び出す場合、複数のCustomDialogControllerが存在し、問題の原因は誤ったCustomDialogControllerの使用、または自身のcontrollerを最後に配置しなかったことによる可能性があります。
分析結果
CustomDialogに複数の他のcontrollerを渡して、そのダイアログ内で別のダイアログを開く場合、自身のcontrollerを他のすべてのcontrollerの後に配置する必要があります。
修正提案
ダイアログのネストされた使用を正しく実現するには、以下の方法が考えられます:
方法1: CustomDialogを使用したネスト
ネストされたダイアログのCustomDialogControllerを上位のダイアログに配置してネストを実現します。自身のcontrollerを他のすべてのcontrollerの後に配置する必要があります。
方法2: UIContextのgetPromptActionを使用
UIContextのgetPromptActionを使用してPromptActionインスタンスを取得し、そのインスタンスのメソッドopenCustomDialogを呼び出します。builderパラメータに異なるダイアログページを渡します。
import { PromptAction } from '@kit.ArkUI'
@Entry
@Component
struct DialogExample {
private dialogId: number = 0
private nestedDialogId: number = 0
private promptInterface: PromptAction = this.getUIContext().getPromptAction()
@Builder
nestedDialogContent() {
Column() {
Text('ネストされたダイアログ')
Button('閉じる').onClick((event: ClickEvent) => {
this.promptInterface.closeCustomDialog(this.nestedDialogId)
})
}
}
@Builder
firstDialogContent() {
Column() {
Text('最初のダイアログ').fontSize(28)
Text('ネストされたダイアログを開く')
.onClick(() => {
this.promptInterface.openCustomDialog({
builder: () => {
this.nestedDialogContent()
}
})
.then((dialogId: number) => {
this.nestedDialogId = dialogId
})
})
Row({ space: 40 }) {
Button('閉じる').onClick(() => {
this.promptInterface.closeCustomDialog(this.dialogId)
})
}
}
.height(180).padding(8).justifyContent(FlexAlign.SpaceBetween)
}
build() {
Row() {
Column({ space: 18 }) {
Text('最初のダイアログを開く')
.fontSize(28)
.onClick(() => {
this.promptInterface.openCustomDialog({
builder: () => {
this.firstDialogContent()
},
}).then((dialogId: number) => {
this.dialogId = dialogId
})
})
}
.width('100%')
}
.height('100%')
}
}
比較表
| 方法 | 注意点 | 利点 |
|---|---|---|
| CustomDialog | CustomDialogでネストされたダイアログを実現する場合、自身のcontrollerを他のすべてのcontrollerの後に配置する必要があります。 | CustomDialogは高いカスタマイズ制御能力を持っています。 |
| promptAction | promptActionでネストされたダイアログを実現する場合、controllerを登録する必要がなく、ダイアログを表示する必要がある際にpromptAction.openCustomDialogを使用するだけです。 | promptActionはより簡単に使用できます。 |