HarmonyOS 鸿蒙Next中关于@CustomDialog的弹窗问题

HarmonyOS 鸿蒙Next中关于@CustomDialog的弹窗问题 现在我有两个@CustomDialog,暂且分别命名为Dialog1和Dialog2。我的Dialog1和Dialog2都设置在应用底部,两个@CustomDialogui设计都是一个stack里面包一个宽高都为100%Column,和一个显示内容的contentView,Column里面是一个blank,blank的宽高都为100%,blank的backgroundColor为Transparent,在点击blank的时候,可以关闭@CustomDialog。我在Dialog1的ui底部设置一行高为62工具栏,通过工具栏里面某个按钮打开Dialog2。现在我希望在打开Dialog2的时候,Dialog2的高度可以往上移62,将Dialog1的工具栏显露出来。我希望在Dialog2打开的时候,Dialog1的工具栏可以显示出来,而且可以和Dialog2一样正常操作。目前我遇到了一个问题,我给Dialog2的blank或者包裹blank的Column设置hitTestBehavior为HitTestMode.Transparent,Dialog2的contentView也设置了margin,我发现实现不了预期效果,即打开Dialog2的时候Dialog1的工具栏可以显示出来,而且可以和Dialog2一样正常操作处理Dialog1的点击事件。怎么做才行


更多关于HarmonyOS 鸿蒙Next中关于@CustomDialog的弹窗问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

可以参考下述demo是否符合您的需求,思路如下:将Dialog2的isModal属性设置为false,将弹窗设置为非模态弹窗,而非模态窗口无蒙层,可透传点击事件,可以操作Dialog1的工具栏。

若是不能解决您的问题,请提供一下以下信息:

1.问题现象(如:问题截图);
2.复现代码(如最小复现demo);

@CustomDialog
struct CustomDialogExampleTwo {
  controllerTwo?: CustomDialogController;

  build() {
    Stack() {
      Column() {
        Blank('Dialog2').height('100%').width('100%').backgroundColor(Color.Gray)
          .onClick(() => {
            if (this.controllerTwo != undefined) {
              this.controllerTwo.close();
            }
          })
      }.height('100%').width('100%').justifyContent(FlexAlign.Center)
    }.backgroundColor(Color.Transparent)
  }
}

@CustomDialog
@Component
struct CustomDialogExample {
  dialogControllerTwo: CustomDialogController | null = new CustomDialogController({
    builder: CustomDialogExampleTwo(),
    alignment: DialogAlignment.Bottom,
    isModal: false, // 将isModal设置为false,将弹窗设置为非模态弹窗,而非模态窗口无蒙层,可透传点击事件
    onWillDismiss: (dismissDialogAction: DismissDialogAction) => {
      console.info(`reason= ${dismissDialogAction.reason}`);
      console.info('dialog onWillDismiss');
      if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {
        dismissDialogAction.dismiss();
      }
      if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {
        dismissDialogAction.dismiss();
      }
    },
    offset: { dx: 0, dy: -62 }
  })
  controller?: CustomDialogController;
  cancel: () => void = () => {
  }
  confirm: () => void = () => {
  }

  build() {
    Stack() {
      Column() {
        Blank().layoutWeight(1)
        Button('Dialog1工具栏')
          .onClick(() => {
            if (this.dialogControllerTwo != null) {
              this.dialogControllerTwo.open();
              console.log('工具栏被点击')
            }
          })
          .height(62)
      }.height('100%').width('100%')
    }.borderRadius(10).backgroundColor(Color.White)
  }
}

@Entry
@Component
struct CustomDialogUser {

  @State textValue: string = ''
  @State inputValue: string = '打开Dialog1'
  dialogController: CustomDialogController | null = new CustomDialogController({
    builder: CustomDialogExample({
      cancel: () => {
        this.onCancel();
      },
      confirm: () => {
        this.onAccept();
      }
    }),
    cancel: this.exitApp,
    autoCancel: true,
    onWillDismiss: (dismissDialogAction: DismissDialogAction) => {
      console.info(`reason= ${dismissDialogAction.reason}`);
      console.info('dialog onWillDismiss');
      if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {
        dismissDialogAction.dismiss();
      }
      if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {
        dismissDialogAction.dismiss();
      }
    },
    alignment: DialogAlignment.Bottom
  })

  // 在自定义组件即将析构销毁时将dialogController置空
  aboutToDisappear() {
    this.dialogController = null; // 将dialogController置空
  }

  onCancel() {
    console.info('Callback when the first button is clicked');
  }

  onAccept() {
    console.info('Callback when the second button is clicked');
  }

  exitApp() {
    console.info('Click the callback in the blank area');
  }

  build() {
    Column() {
      Button(this.inputValue)
        .onClick(() => {
          if (this.dialogController != null) {
            this.dialogController.open();
          }
        }).backgroundColor(0x317aff)
    }.width('100%').margin({ top: 5 })
  }
}

更多关于HarmonyOS 鸿蒙Next中关于@CustomDialog的弹窗问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,@CustomDialog用于创建自定义弹窗组件。通过继承CustomDialogController类并重写build方法,可定义弹窗内容与样式。支持设置弹窗大小、位置及交互事件,例如使用@Builder装饰器构建UI布局。弹窗可通过open()方法显示,close()方法关闭。需注意在aboutToAppear或初始化时绑定控制器,确保生命周期管理正确。

要实现Dialog2打开时Dialog1工具栏保持可见且可交互,关键在于正确设置弹窗层级和事件穿透。建议采用以下方案:

  1. 调整Dialog2布局结构 将Dialog2的Stack顶层Column改为:
Column() {
  // 顶部透明遮罩区(高度为屏幕高度-62)
  Blank()
    .height('100%-62vp')
    .backgroundColor(Color.Transparent)
    .onClick(() => this.dismiss())
  // 内容区上移62vp
  ContentView()
    .margin({ bottom: 62vp })
}
  1. 设置事件穿透 为Dialog2的Blank区域添加:
.hitTestBehavior(HitTestMode.Transparent)
  1. 保持Dialog1工具栏层级 确保Dialog1的工具栏zIndex高于Dialog2背景层:
Toolbar()
  .zIndex(2)
  1. 使用自定义动画 在Dialog2的transition配置中设置从底部向上滑入的动画,初始位置偏移62vp。

这样实现后:

  • Dialog2内容区会上移62vp,露出Dialog1工具栏
  • 点击空白区域可关闭Dialog2而不影响Dialog1
  • Dialog1工具栏始终可接收点击事件
  • 两个弹窗的事件互不干扰

注意检查两个CustomDialog的show方法调用顺序,确保Dialog1作为底层弹窗先显示。

回到顶部