HarmonyOS:弹出框控制器

一、简介

ArkUI的弹出框控制器在绑定弹出框后,可提供对弹出框的操作能力,当前支持关闭功能。可以将控制器传入弹出框内容区域后进行操作。

API version 18开始,可设置controller参数以绑定DialogController控制器,通过控制器能够操作弹出框。

二、使用约束

目前openCustomDialogWithController和presentCustomDialog支持通过controller参数来绑定弹出框进行操作,目前getDialogController支持获取自定义组件所在的弹出框的控制器。
说明 一个弹出框控制器只能绑定一个弹出框,且操作只对该弹出框生效。 使用getDialogController获取弹出框控制器时,如果当前自定义组件不在弹出框中显示则获取为undefined。

三、创建自定义内容为ComponentContent的弹出框控制器

  1. 初始化一个自定义弹出框内容区的入参类,内部包含弹出框控制器。
bash 复制代码
class Params {
  public text: string = ''
  public dialogController: promptAction.CommonController = new promptAction.DialogController()
  constructor(text: string, dialogController: promptAction.CommonController) {
    this.text = text
    this.dialogController = dialogController
  }
}
  1. 初始化一个自定义的弹出框内容区,内部包含一个按钮,该按钮通过该自定义组件自带的弹出框控制器实现关闭功能。
bash 复制代码
@Component
struct MyComponent {
  build() {
    Column({ space: 5 }) {
      Button('点我关闭弹窗:通过自定义组件自带的DialogController')
        .onClick(() => {
          let dialogController: promptAction.DialogController = this.getDialogController()
          if (dialogController !== undefined) {
            dialogController.close()
          }
        })
    }
  }
}
  1. 初始化另一自定义弹出框内容区,其中包含一个Text组件和一个按钮,该按钮通过外部传递的弹出框控制器用于关闭弹出框,并且该内容区还包含前一个自定义弹出框内容区。
bash 复制代码
@Builder
function buildText(params: Params) {
  Column({ space: 5 }) {
    Text(params.text)
      .fontSize(30)
    if (params.dialogController !== undefined) {
      Button('点我关闭弹窗:通过外部传递的DialogController')
        .onClick(() => {
          params.dialogController.close()
        })
    }
    MyComponent()
  }
  .width(300)
  .height(200)
  .backgroundColor('#FFF0F0F0')
}
  1. 初始化一个弹出框控制器,并通过设置控制器参数来初始化一个弹出框内容实体对象。最后,通过调用UIContext中的getPromptAction方法获取PromptAction对象,再通过该对象调用openCustomDialogWithController接口,并且设置初始化的内容实体对象和控制器参数以创建弹出框。
bash 复制代码
let dialogController: promptAction.CommonController = new promptAction.DialogController()
let contentNode: ComponentContent<Object> =
  new ComponentContent(this.getUIContext(), wrapBuilder(buildText), new Params(this.message, dialogController))
this.getUIContext().getPromptAction().openCustomDialogWithController(
  contentNode, dialogController, this.baseDialogOptions).catch((err: BusinessError) => {
  console.error('openCustomDialogWithController error: ' + err.code + ' ' + err.message)
})

四、创建自定义内容为CustomBuilder的弹出框控制器

  1. 初始化一个自定义弹出框内容区,内部包含一个Text组件和一个按钮,该按钮通过外部传递的弹出框控制器实现关闭功能。
bash 复制代码
@Builder customDialogComponent(dialogController: promptAction.DialogController) {
  Column({ space: 5 }) {
    Text(this.message)
      .fontSize(30)
    if (dialogController !== undefined) {
      Button('点击关闭弹窗:通过外部传递的DialogController')
        .onClick(() => {
          dialogController.close()
        })
    }
  }
  .height(200)
  .padding(5)
  .justifyContent(FlexAlign.SpaceBetween)
  .backgroundColor('#FFF0F0F0')
}
  1. 初始化一个弹出框控制器,并通过调用UIContext中的getPromptAction方法获取PromptAction对象,再通过该对象调用presentCustomDialog接口,设置初始化的内容实体对象和控制器参数以创建弹出框。
bash 复制代码
let dialogController: promptAction.CommonController = new promptAction.DialogController()
this.getUIContext().getPromptAction().presentCustomDialog(() => {
  this.customDialogComponent(dialogController)
}, dialogController, this.dialogOptions).catch((err: BusinessError) => {
  console.error('presentCustomDialog error: ' + err.code + ' ' + err.message)
})

五、在CustomDialogController内容区直接获取弹出框控制器

  1. 初始化一个自定义弹出框内容区,内部包含一个Text组件和一个按钮,该按钮通过弹出框控制器关闭弹出框。
bash 复制代码
@CustomDialog
@Component
struct CustomDialogExample {
  controller?: CustomDialogController

  build() {
    Column({ space: 5 }) {
      Text('我是内容')
        .fontSize(30)
      Button('点我关闭弹窗:通过自定义组件自带的DialogController')
        .onClick(() => {
          let dialogController: PromptActionDialogController = this.getDialogController()
          if (dialogController !== undefined) {
            dialogController.close()
          }
        })
    }
    .height(200)
    .backgroundColor('#FFF0F0F0')
  }
}
  1. 初始化一个自定义弹出框构造器,关联自定义弹出框内容区。
bash 复制代码
let customDialogController: CustomDialogController = new CustomDialogController({
  builder: CustomDialogExample(),
})
customDialogController.open()

六、使用控制器获取弹出框的状态

在自定义弹出框场景中,可以通过控制器调用getState接口获取弹出框状态。

初始化一个自定义弹出框内容区,内部包含一个Text组件和一个按钮,该按钮通过调用getState获取当前弹出框状态。

bash 复制代码
@Builder customDialogComponent(dialogController: promptAction.DialogController) {
  Column({ space: 5 }) {
    Text(this.message)
      .fontSize(30)
    if (dialogController !== undefined) {
      Button('点我查询弹窗状态')
        .onClick(() => {
          console.info('state:' + this.dialogController.getState())
        })
    }
  }
  .height(200)
  .padding(5)
  .justifyContent(FlexAlign.SpaceBetween)
  .backgroundColor('#FFF0F0F0')
}

七、完整示例

通过外部传递的弹出框控制器和自定义组件自带的弹出框控制器,在自定义弹出框内容区域内实现关闭功能。
效果图

bash 复制代码
import { ComponentContent, promptAction } from '@kit.ArkUI'
import { BusinessError } from '@kit.BasicServicesKit'

class Params {
  public text: string = ''
  public dialogController: promptAction.CommonController = new promptAction.DialogController()

  constructor(text: string, dialogController: promptAction.CommonController) {
    this.text = text
    this.dialogController = dialogController
  }
}

@Component
struct MyComponent {
  build() {
    Column({ space: 5 }) {
      Button('点我关闭弹窗:通过自定义组件自带的DialogController')
        .onClick(() => {
          let dialogController: promptAction.DialogController = this.getDialogController() // API version 18
          if (dialogController !== undefined) {
            dialogController.close()
          }
        })
    }
  }
}

@Builder
function buildText(params: Params) {
  Column({ space: 5 }) {
    Text(params.text)
      .fontSize(30)
    if (params.dialogController !== undefined) {
      Button('点我关闭弹窗:通过外部传递的DialogController')
        .onClick(() => {
          params.dialogController.close()
        })
    }
    MyComponent()
  }
  .width(300)
  .height(200)
  .backgroundColor('#FFF0F0F0')
}

@CustomDialog
@Component
struct CustomDialogExample {
  controller?: CustomDialogController

  build() {
    Column({ space: 5 }) {
      Text('我是内容')
        .fontSize(30)
      Button('点我关闭弹窗:通过自定义组件自带的DialogController')
        .onClick(() => {
          let dialogController: PromptActionDialogController = this.getDialogController()
          if (dialogController !== undefined) {
            dialogController.close()
          }
        })
    }
    .height(200)
    .backgroundColor('#FFF0F0F0')
  }
}

@Entry
@Component
export struct TestOpenCustomDialog5 {
  private message = '弹窗'

  @Builder
  customDialogComponent(dialogController: promptAction.DialogController) {
    Column({ space: 5 }) {
      Text(this.message)
        .fontSize(30)
      if (dialogController !== undefined) {
        Button('点击关闭弹窗:通过外部传递的DialogController')
          .onClick(() => {
            dialogController.close()
          })
      }
    }
    .height(200)
    .padding(5)
    .justifyContent(FlexAlign.SpaceBetween)
    .backgroundColor('#FFF0F0F0')
  }

  @Builder
  customDialogComponentWithId(dialogId: number, dialogController: promptAction.DialogController) {
    Column({ space: 5 }) {
      Text(this.message)
        .fontSize(30)
      if (dialogId !== undefined) {
        Button('点击关闭弹窗:通过DialogID')
          .onClick(() => {
            this.getUIContext().getPromptAction().closeCustomDialog(dialogId)
          })
      }
      if (dialogController !== undefined) {
        Button('点击关闭弹窗:通过外部传递的DialogController')
          .onClick(() => {
            dialogController.close()
          })
      }
    }
  }

  private baseDialogOptions: promptAction.BaseDialogOptions = {
    isModal: false,
    autoCancel: false
  }
  private dialogOptions: promptAction.DialogOptions = {
    isModal: false,
    autoCancel: false
  }

  openCustomDialogWithController() {
    let dialogController: promptAction.CommonController = new promptAction.DialogController()
    let contentNode: ComponentContent<Object> =
      new ComponentContent(this.getUIContext(), wrapBuilder(buildText),
        new Params(this.message, dialogController))
    this.getUIContext().getPromptAction().openCustomDialogWithController(
      contentNode, dialogController, this.baseDialogOptions).catch((err: BusinessError) => {
      console.error('openCustomDialogWithController error: ' + err.code + ' ' + err.message)
    })
  }

  presentCustomDialogWithCustomBuilder() {
    let dialogController: promptAction.CommonController = new promptAction.DialogController()
    this.getUIContext().getPromptAction().presentCustomDialog(() => {
      this.customDialogComponent(dialogController)
    }, dialogController, this.dialogOptions).catch((err: BusinessError) => {
      console.error('presentCustomDialog error: ' + err.code + ' ' + err.message)
    })
  }

  presentCustomDialogWithCustomBuilderWithId() {
    let dialogController: promptAction.CommonController = new promptAction.DialogController()
    this.getUIContext().getPromptAction().presentCustomDialog((dialogId: number) => {
      this.customDialogComponentWithId(dialogId, dialogController)
    }, dialogController, this.dialogOptions).catch((err: BusinessError) => {
      console.error('presentCustomDialog error: ' + err.code + ' ' + err.message)
    })
  }

  customDialogController() {
    let customDialogController: CustomDialogController = new CustomDialogController({
      builder: CustomDialogExample(),
    })
    customDialogController.open()
  }

  build() {
    Column({ space: 20 }) {
      Button('openCustomDialogWithController弹窗').margin({top: 40})
        .onClick(() => {
          this.openCustomDialogWithController()
        })
      Button('presentCustomDialog+CustomBuilder弹窗')
        .onClick(() => {
          this.presentCustomDialogWithCustomBuilder()
        })
      Button('presentCustomDialog+CustomBuilderWithId弹窗')
        .onClick(() => {
          this.presentCustomDialogWithCustomBuilderWithId()
        })
      Button('CustomDialogController弹窗')
        .onClick(() => {
          this.customDialogController()
        })
    }.width('100%')
  }
}
相关推荐
Magic-ZYJ10 小时前
HarmonyOS Release 构建安全:ArkGuard 混淆、签名配置与秘密管理
安全·华为·harmonyos·移动应用开发·心晴手记
见山是山-见水是水11 小时前
拆解HarmonyOS网络请求适配:原生鸿蒙页面的实现路径与调试方法
华为·harmonyos
m0_7496902312 小时前
【寻迹校园 HarmonyOS NEXT 实战 36】深色模式不是反色:用语义 Token 管理品牌色与状态色
harmonyos·arkts·深色模式·ui设计·主题设计
lqj_本人12 小时前
鸿蒙跨端实战_QT后台切换导致OpenGLES上下文丢失:黑屏自救指南
qt·华为·harmonyos
OH_TPC14 小时前
HarmonyOS APP开发---“数据眼“健康追踪App,需要用到这个库
华为·harmonyos·鸿蒙
lilian23315 小时前
Harmony os 技术实战|拼豆制图49:五组分类视觉规则如何收口成一张配置表
华为·harmonyos
2501_9197490315 小时前
华为鸿蒙免费决策APP—小羊挠头
华为·harmonyos·鸿蒙
m0_7496902315 小时前
【寻迹校园 HarmonyOS NEXT 实战 37】一套 ArkUI 适配四档宽度:sm、md、lg、xl 响应式 Shell 实战
华为·harmonyos·arkui·navigation·响应式布局·多设备适配
RisunJan17 小时前
HarmonyOS 架构精读:从系统分层到应用模型
华为·架构·harmonyos
见山是山-见水是水18 小时前
从需求到页面:鸿蒙原生 Ability 与 ArkTS 交互的 ArkTS 原生实现
华为·harmonyos