场景一:自定义TextPickerDialog

方案:

开发者对于Picker这块常常会有一个误区,在使用Picker这块弹窗的时候优先会使用封装好的PikcerDialog类组件;但是需要注意的是,PikcerDialog类的组件是和系统颜色保持一致的,并不支持自定义;当需要自定义Picker弹窗时,优先考虑自行封装。所以,开发者使用Picker弹窗的时候优先考虑自己使用Picker类组件自行封装。

主要方案就是使用全局自定义弹窗PromptAction.openCustomDialog封装TextPicker组件,然后达成像TextPickerDialog同样的功能,拥有更灵活的自定义能力。

核心代码:

private selectDialogIn: number = 0
private daysDialogIn: string[] = Array(31).fill(0).map((v: string, i) => i + 1).map(n => n.toString());
@State showDayDialogIn: string = ''

@Builder
customDialogComponent() {
  Column() {
    //orange area
    Row() {
      Text(this.showDayDialogIn).fontColor('#FF9A3C').fontSize(15).margin({ left: 10 })
      Text('天以后可以修改').fontColor('#FF9A3C').fontSize(15)
    }
    .height(50).width('100%').alignItems(VerticalAlign.Center).backgroundColor('#FEF2E5')

    // cancal area
    Row() {
      Text('取消').fontColor('#9C9C9C').fontSize(20).margin({ left: 10 })
        .onClick(() => {
          promptAction.closeCustomDialog(this.customDialogComponentId)
          this.showDayDialogIn = ''
        })
      Text('选择持续天数').fontColor('#2D2D2D').fontSize(17)
      Text('确定')
        .fontColor('#507DAF')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ right: 10 })
        .onClick(() => {
          this.showDayDialogIn = ''
          promptAction.closeCustomDialog(this.customDialogComponentId)
        })
    }
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.SpaceBetween)
    .width('100%')
    .height(60)

    // textpicker area
    Row() {
      TextPicker({ range: this.daysDialogIn, selected: this.selectDialogIn })
        .onChange((value: string | string[], index: number | number[]) => {
          this.showDayDialogIn = value.toString()
          console.info('Picker item changed, value: ' + value + ', index: ' + index)
        })
        .canLoop(false)
        .divider({
          strokeWidth: '2px',
          startMargin: 20,
          endMargin: 20,
          color: '#33000000'
        })
        .gradientHeight('60%')
        .disappearTextStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Lighter } })
        .textStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Lighter } })
        .selectedTextStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Normal } })
      Text('天').fontSize(20).fontColor(Color.Black)
    }.width('100%').alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Center).margin({ top: 10 })
  }.width('100%').height(360)
}

场景二:自定义CalendarPickerDialog

效果:

效果说明:此处的场景是一个日历选择弹窗,实现了一个类考勤打卡的demo。

方案:

参考场景1方案。此处的picker弹窗也是基于全局自定义弹窗进行封装的,只是不同上面的自定义TextPickerDialog,calendar没有选择使用官方的calendarPicker组件,而是使用三方库直接封装好的,以下demo是参考三方库@ohmos/calendar实现;当然,开发者也可以自行到三方库中搜寻日历相关关键字,然后挑选适合自己需求的三方库。

核心代码:

@Builder
NormalCalendarBuilder() {
  Column() {
    Row() {
      Text('取消').fontColor('#9C9C9C').fontSize(20).margin({ left: 10 })
        .onClick(() => {
          promptAction.closeCustomDialog(this.normalCalendarDialogId)
        })
      Text('请选择日期').fontSize(17).fontColor('#00aa00').fontWeight(FontWeight.Medium)
      Text('确定')
        .fontColor('#507DAF')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ right: 10 })
        .onClick(() => {
          promptAction.closeCustomDialog(this.normalCalendarDialogId)
        })
    }
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.SpaceBetween)
    .width('100%')
    .height(60)

    HmCalendar({
      color: '#00aa00',
      selectedDays: this.normalCalendarSelectedDay,
      onClickDate: (date: string) => {
        let today: HmCalendarSelectedDay = { date: date }
        if (this.normalCalendarSelectedDay.length === 0) {
          this.normalCalendarSelectedDay.push(today)
        }
        // 判断今天是否已经打卡
        if (!this.normalCalendarSelectedDay.includes(today)) {
          this.normalCalendarSelectedDay.push(today)
        }
      }
    })
      .borderRadius(8)
      .border({ width: 0.5, color: '#ededed' })
      .shadow({ color: '#ededed', radius: 16 })
      .height('50%')
  }
  .width('100%')
}

场景三:多列的TextPicker的实现

效果:

效果说明:文档当中只有最多3列的TextPicker,此处是4列的TextPicker。

方案:

如下代码所示,传入几列的数据,TextPicker就会渲染出几列的数据;且TextPicker中的range是支持二维数组的。

核心代码:

@Entry
@Component
export struct MultipleColumnsTextPicker {
  private cascade: TextCascadePickerRangeContent[] = [
    {
      text: '辽宁省',
      children: [{
        text: '沈阳市',
        children: [{
          text: '沈河区',
          children: [{ text: '大西街道' },
            { text: '滨河街道' },
            { text: '万莲街道' },
            { text: '大南街道' },
            { text: '山东庙街道' },
            { text: '朱剪炉街道' },
            { text: '东陵街道' }]
        }, { text: '和平区' }, { text: '浑南区' }]
      },
        { text: '大连市', children: [{ text: '中山区' }, { text: '金州区' }, { text: '长海县' }] }]
    },
    {
      text: '吉林省',
      children: [{ text: '长春市', children: [{ text: '南关区' }, { text: '宽城区' }, { text: '朝阳区' }] },
        { text: '四平市', children: [{ text: '铁西区' }, { text: '铁东区' }, { text: '梨树县' }] }]
    },
    {
      text: '黑龙江省',
      children: [{ text: '哈尔滨市', children: [{ text: '道里区' }, { text: '道外区' }, { text: '南岗区' }] },
        { text: '牡丹江市', children: [{ text: '东安区' }, { text: '西安区' }, { text: '爱民区' }] }]
    }
  ]

  build() {
    NavDestination() {
      Column() {
        Row() {
          Text('4列TextPicker实现方式')
        }
        .width('100%')
        .height(70)
        .justifyContent(FlexAlign.SpaceAround)
        .alignItems(VerticalAlign.Center)

        TextPicker({ range: this.cascade })
          .onChange((value: string | string[], index: number | number[]) => {
            console.info('TextPicker 多列联动:onChange ' + JSON.stringify(value) + ', ' + 'index: ' +
            JSON.stringify(index))
          })
      }
    }
  }
}

HarmonyOS码上奇行
9.2k 声望3.3k 粉丝

欢迎关注 HarmonyOS 开发者社区:[链接]