1

目录

  • 前言
  • 关于弹窗
  • TextPicker基础
  • 使用案例:CustomDialog+TextPicker组合
  • 测试和优化
  • 最后

    前言

    在移动应用开发中,弹框是一种常见的用户交互组件,用于在应用界面上提供额外的信息或操作选项,也是移动开发中必用的功能,实际开发中系统提供的弹框往往不能完全满足实际业务需求,很多时候需要根据业务需求对弹框内容进行自定义,但凡遇到自定义弹框及弹框内部内容,就需要根据实际情况进行组合式使用。同理,在HarmonyOS开发中系统也提供了弹框的使用及自定义弹框的使用方法,可以说是提供了丰富的API来支持自定义弹框的开发,这可以让开发者根据自己的需求定制独特的用户界面和交互体验。那么本文就来分享一个实际应用中比较常用的自定义弹框组合,即结合CustomDialog和TextPicker组件在HarmonyOS中实现一个自定义弹框的使用案例,方便大家学习和使用。

    关于弹窗

    做过移动端甚至前端开发的小伙伴想必用过弹窗功能,其实弹窗就是一种浮动窗口,主要用于在应用界面上显示额外的信息或提供用户操作选项。而在HarmonyOS开发中,弹窗分为七种类型:AlertDialog、ActionSheet、CustomDialog、CalendarPickerDialog、DatePickerDialog、TimePickerDialog和TextPickerDialog。其他六种弹窗是系统预定义的弹框,而剩下的CustomDialog弹窗是允许开发者自定义弹窗的布局和内容的。

    1、CustomDialog弹窗

    由于本文主要是分享关于CustomDialog弹窗的,所以这里只单独详细介绍CustomDialog弹窗,其他弹窗内容这里不再过多介绍,大家可以自行去鸿蒙官网查阅。CustomDialog是通过CustomDialogController类显示的自定义弹窗,在使用弹窗组件时,我们可优先考虑自定义弹窗,这样便于自定义弹窗的样式与内容,方便我们开发出更适合实际业务场景的弹窗。

    2、系统接口

    关于CustomDialog弹窗的使用,系统提供了一个接口来操作的,即CustomDialogController(value: CustomDialogControllerOptions) 接口。调用的时候,需要配置自定义弹窗的参数,但是有一点需要我们特别注意:自定义弹窗的所有参数,不支持动态刷新。

    3、导入CustomDialogController

    在使用的时候,需要导入对象,具体方式:dialogController : CustomDialogController | null = new CustomDialogController(CustomDialogControllerOptions) 。需要注意的是,CustomDialogController仅在作为@CustomDialog和@Component struct的成员变量,且在@Component struct内部定义时赋值才有效,这一点一定要记住。关于显示或者关闭自定义弹窗,有2个方法来分别控制的。

    (1)open方法

    open()是显示自定义弹窗内容,允许多次使用,但如果弹框为SubWindow模式,则该弹框不允许再弹出SubWindow弹框,具体方法:open(): void 。

    (2)close方法

    close()是关闭显示的自定义弹窗,若已关闭,则不生效,具体方法:close(): void 。

    TextPicker基础

    再来分享一下TextPicker相关的内容,TextPicker是HarmonyOS中用于滑动选择文本内容的组件,它可以提供多种文本选择模式,比如单选、多选等。在实际应用中,TextPicker通常用于实现复杂的文本选择功能,比如日期选择、时间选择、菜单选择等。

    1、接口使用

    TextPicker相关的使用,是借助接口:TextPicker(options?: TextPickerOptions) 来实现的,主要是根据range指定的选择范围创建文本选择器。

    2、TextPickerOptions

    关于TextPickerOptions对象,它有三个参数:range、selected、value。具体的释义来源于鸿蒙官网API,具体内容如下表所示:
    image.png

    3、属性使用

    关于TextPicker的属性使用,有八个常用属性:defaultPickerItemHeight(设置Picker各选择项的高度)、disappearTextStyle(设置所有选项中最上和最下两个选项的文本颜色、字号、字体粗细)、textStyle(设置所有选项中除了最上、最下及选中项以外的文本颜色、字号、字体粗细)、selectedTextStyle(设置选中项的文本颜色、字号、字体粗细)、selectedIndex(设置默认选中项在数组中的索引值,优先级高于options中的选中值。单列数据选择器使用number类型;多列、多列联动数据选择器使用number[]类型)、canLoop(设置是否可循环滚动)、divider(设置分割线样式,不设置该属性则按“默认值”展示分割线)、gradientHeight(设置渐隐效果高度,不设置该属性则显示默认渐隐效果)。

    4、点击事件

    TextPicker的事件有三个:onAccept、onCancel、onChange。

    (1)onAccept方法

    onAccept()点击弹窗中的“确定”按钮时触发该回调,这个事件仅在文本滑动选择器弹窗中生效,具体事件方法:onAccept(callback: (value: string, index: number) => void)

    (2)onCancel方法

    onCancel()点击弹窗中的“取消”按钮时触发该回调,这个事件仅在文本滑动选择器弹窗中生效,具体事件方法:onCancel(callback: () => void)

    (3)onChange方法

    onChange()滑动选中TextPicker文本内容后,触发该回调。当显示文本或图片加文本列表时,value值为选中项中的文本值,当显示图片列表时,value值为空,具体事件方法:onChange(callback: (value: string | string[], index: number | number[]) => void)
    使用案例:CustomDialog+TextPicker组合
    由于最近在使用HarmonyOS开发一款应用,正好也根据业务实际需要,分析之后发现,只有通过CustomDialog+TextPicker组合才能实现业务要求的效果,接下来就来详细来分享具体的使用,方便大家学习使用。

  • 场景描述
    实际业务场景:需要在应用中实现一个功能,允许用户点击列表某一个行,然后弹出一个底部弹出框,弹窗内容显示自定义内容选项,包括两层级联,在用户选择第一级滑动内容之后,二级内容根据一级内容进行关联显示,用户选择完成之后,显示最终的选中结果。这就需要使用CustomDialog来创建一个自定义的内容选择弹框,并在其中嵌入TextPicker组件来实现自定义内容选择功能。
  • 具体实现
    由于篇幅原因,这里直接把自定义的CustomDialog+TextPicker组合弹框文件分享出来,然后再分享一下具体调用自定义弹窗的使用部分。
    (1)CustomDialog+TextPicker组合弹框文件
// ContentDialog.ets文件
import { MchtModel } from 'libFramework';

@Component
@CustomDialog
struct ContentDialog {
  controller: CustomDialogController // 控制器
  @Prop unContent: MchtModel[]; // 数据源
  @State message: string = '';

  @State range: string[][] = [[''], ['']]
  @State selected: number[] = [0, 0]
  // values中设置的内容必须 在 range 中存在,否则会崩溃
  @State values: string[] = ['', '']
  @State textPickerOption: TextCascadePickerRangeContent[] = []
  @State showSheet: boolean = false
  // 定时器 id
  timeId: number = -1
  // 链式编程写法
  aboutToAppear(): void {
    this.getAllData()
  }
  // 获取数据
  getAllData() {
    this.unContent?.forEach((item) => {
      let child: TextCascadePickerRangeContent[] = []
      item.shopInf.forEach((shem) => {
        child.push({ text: shem.shom ? shem.shom : shem.shme })
      })
      this.textPickerOption.push({
        text: item.mchm,
        children: child
      })
    })
  }

  build() {
    Column() {
      Row() {
        Text('取消')
          .textAlign(TextAlign.Center)
          .fontColor(Color.Blue)
          .padding(10)
          .onClick(() => {
            this.controller.close()
          })

        Text('title')
          .layoutWeight(1)
          .fontColor(Color.Blue)
          .fontSize(20)
          .textAlign(TextAlign.Center)
          .fontWeight(FontWeight.Bold)
          .padding(10)
          .onClick(() => {
            this.showSheet = true
          })

        Text('确定')
          .fontColor(Color.Blue)
          .textAlign(TextAlign.Center)
          .padding(10)
          .onClick(() => {
            this.controller.close()
          })
      }
      .margin({ top: 10 })
      Divider()
      TextPicker({
        range: this.textPickerOption,
        selected: $$this.selected,
        value: $$this.values
      })
        .canLoop(false)
        .onChange(async (value, index) => {})
    }
  }
}

export { ContentDialog }

(2)具体使用ContentDialog的地方

//AccountItem.ets文件
import {
  MchtModel,
} from 'libFramework'
import { ContentDialog } from '../dialog/ContentDialog'
import { DialogBtnClick } from '../dialog/DialogCallback'

export type TypeRecord = string | boolean | number | object;

@Component
export struct AccountItem {

  //数据源
  @State unReadContent: MchtModel[] = []

  @State isCloseCommonDialog: boolean = false;
  aboutDialog: CustomDialogController = new CustomDialogController({
    builder: ContentDialog({ unContent: this.unContent }),
    customStyle: false, // 按照弹层的样式来渲染
    autoCancel: false,
    width: '100%',
    height: 260,
    cornerRadius: 10,
    alignment: DialogAlignment.Bottom
  })


  build() {
    Row() {
      Row() {
        Image($r('app.media.head'))
          .width($r('app.float.common_92'))
          .height($r('app.float.common_92'))
          .borderRadius('100%')
          .margin({ right: $r('app.float.common_20') })
        Column() {
          Row() {
            Text('title >')
              .fontSize($r('app.float.common_30'))
              .fontColor(Color.Gray)
              .onClick(() => {
                this.aboutDialog.open(); //打开自定义弹框
              })
          }.margin({
            top: $r('app.float.common_5')
          })
          .justifyContent(FlexAlign.Start)
          .width('100%')
        }.layoutWeight(1)
      }
      .height($r('app.float.common_160'))
      .justifyContent(FlexAlign.Start)
    }
    .height($r('app.float.common_120'))
    .padding(5)
    .margin(5)
    .backgroundColor(Color.White)
  }
}

(3)实现效果
由于自定义弹框使用案例是以实际业务需求来实现的,所以肯定会和其他有需要的小伙伴的需求不一样,不能直接使用,那就需要大家根据自己的实际业务需求来进行改造,其实这个功能实现起来不复杂,只是需要细心去实现。本文示例实现效果具体如下所示:
image.png
image.png

测试和优化

通过上面的具体实现,基本完成了自定义弹框使用的整个业务开发内容,但是开发任务还不算全部结束,因为还需要在完成CustomDialog和TextPicker的实现后,进行充分的测试和修改,尤其是比较常见的防抖等操作的处理,确保自定义弹框在生产环境中能够稳定的显示和隐藏正常,自定义选择功能正确。还有就是,需要根据测试结果进行必要的优化,提升功能的坚固性和良好的用户体验。

最后

通过本文关于自定义弹框基础知识和实际应用示例的分享,大家学习了如何在HarmonyOS开发中结合CustomDialog和TextPicker组件实现自定义弹框的业务场景需求。其实在实际开发过程中,真是的业务需求是非常复杂多样的,单拿自定义弹框的需求来讲,不同业务对弹框的需求大不相同,所以系统自带的弹框是远远不能满足实际需求的,这就需要使用自定义弹框。就拿本文这种组合使用来讲,在实际开发过程中我们可以根据具体需求,灵活地使用 CustomDialog 和 TextPicker,不仅可以提供丰富的用户交互体验,还可以根据具体需求进行定制化开发;但是也要注意用户体验的设计,确保应用的易用性和可访问性。随着HarmonyOS生态的不断发展,期待更多的开发者能够利用这些组件创造出更多优秀的应用,让我们一起在HarmonyOS开发中享受编程带来的乐趣吧!


三掌柜
33.6k 声望7.8k 粉丝

一分耕耘,不一定有一分收获,但十分耕耘,一定会有一分收获!