HarmonyOS Next 中的自定义弹出框 用法

HarmonyOS Next弹出框概述及分类

弹出框是一种模态窗口,通常用于在保持当前上下文环境的同时,临时展示用户需关注的信息或待处理的操作。用户需在模态弹出框内完成相关交互任务之后,才能退出模态模式。弹出框可以不与任何组件绑定,其内容通常由多种组件组成,如文本、列表、输入框、图片等,以实现布局。ArkUI当前提供了自定义固定样式两类弹出框组件。

  • 自定义弹出框: 开发者需要根据使用场景,传入自定义组件填充在弹出框中实现自定义的弹出框内容。主要包括基础自定义弹出框 (CustomDialog)、不依赖UI组件的自定义弹出框 (openCustomDialog)。
  • 固定样式弹出框: 开发者可使用固定样式弹出框,指定需要显示的文本内容和按钮操作,完成简单的交互效果。主要包括警告弹窗 (AlertDialog)、列表选择弹窗 (ActionSheet)、选择器弹窗 (PickerDialog)、对话框 (showDialog)、操作菜单 (showActionMenu)。

本文主要是介绍自定义弹出框的使用,固定样式弹出框可以参考官方文档,自定义弹出框主要有两种实现方式:

1、基础自定义弹出框 (CustomDialog)(不推荐)

2、不依赖UI组件的全局自定义弹出框 (openCustomDialog)(推荐)

基础自定义弹出框 (CustomDialog)

CustomDialog是自定义弹出框,可用于广告、中奖、警告、软件更新等与用户交互响应操作。通过CustomDialogController类显示自定义弹窗。使用弹窗组件时,可优先考虑自定义弹窗,便于自定义弹窗的样式与内容。

1、@CustomDialog装饰器

使用@CustomDialog装饰器装饰自定义弹出框,可在此装饰器内自定义弹出框内容。这里在装饰器内添加确定和取消按钮,也可以同时添加数据函数。

js 复制代码
@CustomDialog
struct CustomDialogExample {
  cancel?: () => void
  confirm?: () => void
  controller: CustomDialogController

  build() {
    Column() {
      Text('我是内容').fontSize(20).margin({ top: 10, bottom: 10 })
      Flex({ justifyContent: FlexAlign.SpaceAround }) {
        Button('cancel')
          .onClick(() => {
            this.controller.close()
            if (this.cancel) {
              this.cancel()
            }
          }).backgroundColor(0xffffff).fontColor(Color.Black)
        Button('confirm')
          .onClick(() => {
            this.controller.close()
            if (this.confirm) {
              this.confirm()
            }
          }).backgroundColor(0xffffff).fontColor(Color.Red)
      }.margin({ bottom: 10 })
    }
  }
}

创建构造器,与装饰器呼应相连。页面内需要在构造器内进行接收,同时创建相应的函数操作。

js 复制代码
@Entry
@Component
struct CustomDialogUser {
  dialogController: CustomDialogController = new CustomDialogController({
    builder: CustomDialogExample({
      cancel: ()=> { this.onCancel() },
      confirm: ()=> { this.onAccept() },
    }),
  })

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

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

  build() {
    Column() {
      Button('click me')
        .onClick(() => {
          this.dialogController.open()
        })
    }.width('100%').margin({ top: 5 })
  }
}

2、CustomContentDialog

使用CustomContentDialog自定义弹出框,可在此自定义内容区弹出框,同时支持定义操作区按钮样式。从API version 12开始支持使用。

名称 类型 必填 装饰器类型 说明
controller CustomDialogController - 弹出框控制器。说明: 未使用@Require装饰,构造时不强制校验参数。
contentBuilder () => void @BuilderParam 弹出框内容。
primaryTitle ResourceStr - 弹出框标题。
secondaryTitle ResourceStr - 弹出框辅助文本。
localizedContentAreaPadding LocalizedPadding - 弹出框内容区内边距。
contentAreaPadding Padding - 弹出框内容区内边距。设置了localizedContentAreaPadding属性时该属性不生效。
buttons ButtonOptions[] - 弹出框操作区按钮,最多支持4个按钮。
theme Theme CustomTheme - 主题信息,可以是CustomTheme或从onWillApplyTheme中获取的Theme实例。
themeColorMode ThemeColorMode - 自定义弹窗深浅色模式。

支持自定义内容弹出框,包含contentBuilder、buttons等内容。和@CustomDialog装饰器一样,CustomContentDialog也可以添加按钮和数据,如果需要完全自定义弹框样式,可以只设置contentBuilder函数参数用来实现自定义弹框。

js 复制代码
import { CustomContentDialog } from '@kit.ArkUI'

@Entry
@Component
struct Index {
  dialogController: CustomDialogController = new CustomDialogController({
    builder: CustomContentDialog({
      primaryTitle: '标题',
      secondaryTitle: '辅助文本',
      contentBuilder: () => {
        this.buildContent();
      },
      buttons: [
        { 
          value: '按钮1',
          buttonStyle: ButtonStyleMode.TEXTUAL, 
          action: () => {
            console.info('Callback when the button is clicked')
          }
        },
        {
          value: '按钮2',
          buttonStyle: ButtonStyleMode.TEXTUAL,
          role: ButtonRole.ERROR
        }
      ],
    }),
  });

  build() {
    Column() {
      Button("支持自定义内容弹出框")
        .onClick(() => {
          this.dialogController.open()
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
  
  // 自定义弹出框的内容区
  @Builder
  buildContent(): void {
    Column() {
      Text('内容区')
    }
    .width('100%')
  }
}

不依赖UI组件的全局自定义弹出框 (openCustomDialog)

先对于CustomDialogController,官方更推荐我们使用openCustomDialog来实现自定义弹出框。

由于CustomDialogController在使用上存在诸多限制,不支持动态创建也不支持动态刷新,在相对较复杂的应用场景中推荐使用UIContext中获取到的PromptAction对象提供的openCustomDialog接口来实现自定义弹出框。

弹出框(openCustomDialog)存在两种入参方式创建自定义弹出框:

  • openCustomDialog(传参为ComponentContent形式):通过ComponentContent封装内容可以与UI界面解耦,调用更加灵活,可以满足开发者的封装诉求。拥有更强的灵活性,弹出框样式是完全自定义的,且在弹出框打开之后可以使用updateCustomDialog方法动态更新弹出框的一些参数。
  • openCustomDialog(传builder的形式):相对于ComponentContent,builder必须要与上下文做绑定,与UI存在一定耦合。此方法有用默认的弹出框样式,适合于开发者想要实现与系统弹窗默认风格一致的效果。

1、初始化弹出框配置

获取PromptAction对象,初始化弹出框配置,可在配置中修改弹窗位置,动画等相关配置。

创建ComponentContent,ComponentContent用于定义自定义弹出框的内容。其中,wrapBuilder(radioDialogView)封装自定义组件。

js 复制代码
  // 设置对话框内容组件(支持链式调用)
  init(context: UIContext, radioSelectBean: RadioSelectBean): RadioAppDialog {
    this.contentNode = new ComponentContent(context, wrapBuilder<[RadioSelectBean]>(radioDialogView), radioSelectBean);
    this.promptAction = context.getPromptAction();
    this.options = {
      alignment: DialogAlignment.Bottom,
      transition: TransitionEffect.move(TransitionEdge.BOTTOM)
        .animation({ duration: 300 }),
    }
    return this
  }

2、打开自定义弹出框。

通过调用openCustomDialog接口打开的弹出框默认为customStyle为true的弹出框,即弹出框的内容样式完全按照contentNode自定义样式显示。

js 复制代码
 // 显示自定义对话框
  show() {
    if (this.contentNode !== null) {
      this.promptAction?.openCustomDialog(this.contentNode, this.options)
        .then(() => {
          console.info('打开自定义对话框完成')
        })
        .catch((error: BusinessError) => {
          // 错误处理:获取错误码和信息
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`打开对话框参数错误,错误码:${code},信息:${message}`);
        })
    }
  }

3、关闭自定义弹出框

关闭弹出框之后若需要释放对应的ComponentContent,则需要调用ComponentContent的dispose方法。

tip:关闭弹出框需要传人待关闭的ComponentContent对象。

js 复制代码
 // 关闭自定义对话框
  close() {
    if (this.contentNode !== null) {
      this.promptAction?.closeCustomDialog(this.contentNode)
        .then(() => {
          this.contentNode?.dispose()
          console.info('关闭自定义对话框完成')
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`关闭对话框参数错误,错误码:${code},信息:${message}`);
        })
    }
  }

4、更新自定义弹出框的内容

若需要更新弹出框中自定义组件的内容可以通过ComponentContent提供的update方法来实现。这里传人的数据对象就事显示的时候传人的数据。

js 复制代码
  //更新对话框数据
  updateData(radioSelectBean: RadioSelectBean) {
    this.contentNode?.update(radioSelectBean)
  }

5、完整代码

js 复制代码
// 导入ArkUI的对话框操作模块和基础服务错误类型
import { ComponentContent, curves, PromptAction, promptAction } from "@kit.ArkUI";
import { BusinessError } from "@kit.BasicServicesKit";
import { RadioSelectBean } from "../model/HomeModel";
import { radioDialogView } from "../view/GlobalBuildView";

// 自定义单选对话框类
export class RadioAppDialog {
  // 单例实例
  private static instance: RadioAppDialog;
  // 静态属性声明
  contentNode?: ComponentContent<Object>; // 对话框内容组件
  options?: promptAction.BaseDialogOptions; // 对话框基础配置选项
  promptAction?: PromptAction

  // 私有化构造函数
  private constructor() {
    console.info('创建自定义对话框单例');
  }

  /**
   * 获取单例实例(静态方法)
   * @returns 返回全局唯一实例
   */
  public static getInstance(): RadioAppDialog {
    if (!RadioAppDialog.instance) {
      RadioAppDialog.instance = new RadioAppDialog();
    }
    return RadioAppDialog.instance;
  }

  /**
   * 重置单例实例(用于测试或特殊场景)
   */
  public static resetInstance(): void {
    RadioAppDialog.instance = new RadioAppDialog();
  }


  // 设置对话框内容组件(支持链式调用)
  init(context: UIContext, radioSelectBean: RadioSelectBean): RadioAppDialog {
    this.contentNode = new ComponentContent(context, wrapBuilder<[RadioSelectBean]>(radioDialogView), radioSelectBean);
    this.promptAction = context.getPromptAction();
    this.options = {
      alignment: DialogAlignment.Bottom,
      transition: TransitionEffect.move(TransitionEdge.BOTTOM)
        .animation({ duration: 300 }),
    }
    return this
  }

  // 设置对话框选项(支持链式调用)
  setOptions(options: promptAction.BaseDialogOptions): RadioAppDialog {
    this.options = options;
    return this;
  }

  //更新对话框数据
  updateData(obj?: Object) {
    this.contentNode?.update(obj)
  }


  // 显示自定义对话框
  show() {
    if (this.contentNode !== null) {
      this.promptAction?.openCustomDialog(this.contentNode, this.options)
        .then(() => {
          console.info('打开自定义对话框完成')
        })
        .catch((error: BusinessError) => {
          // 错误处理:获取错误码和信息
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`打开对话框参数错误,错误码:${code},信息:${message}`);
        })
    }
  }

  // 关闭自定义对话框
  close() {
    if (this.contentNode !== null) {
      this.promptAction?.closeCustomDialog(this.contentNode)
        .then(() => {
          this.contentNode?.dispose()
          console.info('关闭自定义对话框完成')
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`关闭对话框参数错误,错误码:${code},信息:${message}`);
        })
    }
  }

  // 更新对话框配置
  updateDialog(options: promptAction.BaseDialogOptions) {
    if (this.contentNode !== null) {
      this.promptAction?.updateCustomDialog(this.contentNode, options)
        .then(() => {
          console.info('更新对话框配置完成')
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`更新对话框参数错误,错误码:${code},信息:${message}`);
        })
    }
  }
}
相关推荐
别说我什么都不会2 小时前
OpenHarmony源码分析之分布式软总线:trans_service模块(5)/TCP会话管理
分布式·嵌入式·harmonyos
二流小码农3 小时前
鸿蒙开发:ArkTs语言注释
android·ios·harmonyos
二流小码农3 小时前
鸿蒙开发:权限授权封装
android·ios·harmonyos
H.ZWei4 小时前
鸿蒙应用开发—ZDbUtil高效使用数据库
数据库·harmonyos·鸿蒙·zdbutil
lqj_本人5 小时前
鸿蒙 @ohos.arkui.drawableDescriptor (DrawableDescriptor)
华为·harmonyos
lqj_本人5 小时前
鸿蒙 Next 实现单例
华为·单例模式·harmonyos
lqj_本人5 小时前
鸿蒙 @ohos.arkui.componentUtils (componentUtils)
华为·harmonyos
看客随心5 小时前
鸿蒙路由 HMRouter 配置及使用 三 全局拦截器使用
华为·harmonyos
轻口味5 小时前
【每日学点HarmonyOS Next知识】图片拖动、动画放大、列表高度、返回键监听、分割线颜色
华为·harmonyos·harmonyosnext