HarmonyOS 5: 複数ダイアログの連続表示における問題と解決策

問題現象

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はより簡単に使用できます。

タグ: HarmonyOS CustomDialog ダイアログ連携 UI開発 モバイルアプリ

7月9日 21:53 投稿