TimePicker时间选择器基础设置

文章简介

TimePicker是HarmonyOS开发中常用的时间选择组件,本文将详细介绍其基础使用方法、属性配置和实际应用场景。通过本文,您将掌握TimePicker的核心功能和进阶技巧。

官方参考资料:

一、TimePicker基础介绍

1.1 什么是TimePicker

TimePicker是HarmonyOS ArkUI框架提供的时间选择器组件,允许用户通过可视化界面选择小时、分钟和秒。

1.2 核心特点

  • 直观易用:提供滚动选择器界面
  • 高度可定制:支持多种时间格式和显示模式
  • 响应式设计:自动适配不同屏幕尺寸
  • 国际化支持:内置多语言时间格式

二、基础使用方法

2.1 创建基本TimePicker

// 基本TimePicker示例
@Entry
@Component
struct BasicTimePickerExample {
  @State selectedTime: Date = new Date()

  build() {
    Column() {
      TimePicker({
        selected: this.selectedTime
      })
        .onChange((value: Date) => {
          this.selectedTime = value
          console.info('Selected time: ' + value.toLocaleTimeString())
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

2.2 基础属性配置

@Component
struct ConfiguredTimePickerExample {
  @State currentTime: Date = new Date(2024, 5, 15, 14, 30, 0)

  build() {
    TimePicker({
      selected: this.currentTime
    })
    .useMilitaryTime(false)  // 使用12小时制
    .backgroundColor(Color.White)
    .width(200)
    .height(150)
  }
}

三、TimePicker核心属性详解

3.1 主要属性列表

属性名称 数据类型 默认值 描述
selected Date 当前时间 设置或获取选中的时间
useMilitaryTime boolean false 是否使用24小时制
backgroundColor Color - 背景颜色
textColor Color - 文字颜色
disabled boolean false 是否禁用组件

3.2 时间范围设置

@Component
struct TimeRangePickerExample {
  @State startTime: Date = new Date(2024, 5, 15, 8, 0, 0)
  @State endTime: Date = new Date(2024, 5, 15, 18, 0, 0)
  @State selectedTime: Date = new Date(2024, 5, 15, 10, 0, 0)

  build() {
    TimePicker({
      selected: this.selectedTime
    })
    .onChange((value: Date) => {
      // 限制选择时间在指定范围内
      if (value < this.startTime || value > this.endTime) {
        promptAction.showToast({
          message: '请选择8:00-18:00之间的时间',
          duration: 2000
        })
        return
      }
      this.selectedTime = value
    })
  }
}

四、事件处理机制

4.1 时间变化监听

@Component
struct TimePickerWithEvents {
  @State selectedTime: Date = new Date()
  @State timeString: string = ''

  build() {
    Column() {
      TimePicker({
        selected: this.selectedTime
      })
      .onChange((value: Date) => {
        this.selectedTime = value
        this.timeString = this.formatTime(value)
        console.info('时间已改变: ' + this.timeString)
      })

      Text(this.timeString)
        .fontSize(20)
        .margin({ top: 20 })
    }
  }

  // 格式化时间显示
  private formatTime(date: Date): string {
    const hours = date.getHours().toString().padStart(2, '0')
    const minutes = date.getMinutes().toString().padStart(2, '0')
    return `${hours}:${minutes}`
  }
}

4.2 自定义验证逻辑

@Component
struct ValidatedTimePicker {
  @State selectedTime: Date = new Date()

  build() {
    TimePicker({
      selected: this.selectedTime
    })
    .onChange((value: Date) => {
      if (this.isValidBusinessTime(value)) {
        this.selectedTime = value
      } else {
        promptAction.showToast({
          message: '非工作时间,请重新选择',
          duration: 3000
        })
      }
    })
  }

  // 验证是否为工作时间(9:00-17:00)
  private isValidBusinessTime(time: Date): boolean {
    const hour = time.getHours()
    return hour >= 9 && hour <= 17
  }
}

五、样式自定义指南

5.1 外观定制

@Component
struct StyledTimePicker {
  @State currentTime: Date = new Date()

  build() {
    TimePicker({
      selected: this.currentTime
    })
    .backgroundColor('#F5F5F5')
    .textColor(Color.Black)
    .selectedTextColor(Color.Blue)
    .normalTextColor(Color.Gray)
    .height(180)
    .width(280)
    .borderRadius(10)
    .padding(10)
  }
}

5.2 主题适配

@Component
struct ThemedTimePicker {
  @State isDarkMode: boolean = false
  @State selectedTime: Date = new Date()

  build() {
    TimePicker({
      selected: this.selectedTime
    })
    .backgroundColor(this.isDarkMode ? Color.Black : Color.White)
    .textColor(this.isDarkMode ? Color.White : Color.Black)
    .selectedTextColor(this.isDarkMode ? Color.Cyan : Color.Blue)
  }
}

六、实际应用案例

6.1 预约系统时间选择

@Entry
@Component
struct AppointmentSystem {
  @State appointmentTime: Date = new Date()
  @State availableSlots: string[] = ['09:00', '10:30', '14:00', '15:30']

  build() {
    Column({ space: 20 }) {
      Text('选择预约时间')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)

      TimePicker({
        selected: this.appointmentTime
      })
      .useMilitaryTime(true)
      .onChange((value: Date) => {
        this.validateAppointmentTime(value)
      })

      Text(this.formatAppointmentTime())
        .fontSize(18)
        .fontColor(Color.Green)
    }
    .padding(20)
  }

  private validateAppointmentTime(time: Date): void {
    const timeStr = this.formatTimeForValidation(time)
    if (!this.availableSlots.includes(timeStr)) {
      promptAction.showToast({
        message: '该时间段不可预约',
        duration: 2000
      })
    }
  }

  private formatAppointmentTime(): string {
    return `您选择的预约时间: ${this.appointmentTime.getHours()}:${this.appointmentTime.getMinutes().toString().padStart(2, '0')}`
  }

  private formatTimeForValidation(date: Date): string {
    return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
  }
}

6.2 多时区时间选择器

@Component
struct MultiTimezoneTimePicker {
  @State localTime: Date = new Date()
  @State utcTime: Date = new Date()
  @State selectedTimezone: string = 'UTC+8'

  build() {
    Column({ space: 15 }) {
      TimePicker({
        selected: this.localTime
      })
      .onChange((value: Date) => {
        this.localTime = value
        this.updateUTCTime(value)
      })

      Text(`本地时间: ${this.formatTime(this.localTime)}`)
      Text(`UTC时间: ${this.formatTime(this.utcTime)}`)
      Text(`时区: ${this.selectedTimezone}`)
    }
  }

  private updateUTCTime(localTime: Date): void {
    const utc = new Date(localTime.getTime() - (8 * 60 * 60 * 1000)) // UTC+8转换
    this.utcTime = utc
  }

  private formatTime(date: Date): string {
    return date.toTimeString().split(' ')[0]
  }
}

七、进阶功能实现

7.1 动态时间间隔

@Component
struct IntervalTimePicker {
  @State selectedTime: Date = new Date()
  @State timeInterval: number = 30 // 分钟间隔

  aboutToAppear() {
    // 初始化时间,对齐到最近的间隔
    this.alignToInterval()
  }

  build() {
    TimePicker({
      selected: this.selectedTime
    })
    .onChange((value: Date) => {
      this.alignToSpecificInterval(value)
    })
  }

  private alignToSpecificInterval(time: Date): void {
    const minutes = time.getMinutes()
    const alignedMinutes = Math.round(minutes / this.timeInterval) * this.timeInterval
    time.setMinutes(alignedMinutes)
    this.selectedTime = new Date(time.getTime())
  }

  private alignToInterval(): void {
    const now = new Date()
    const minutes = now.getMinutes()
    const alignedMinutes = Math.floor(minutes / this.timeInterval) * this.timeInterval
    now.setMinutes(alignedMinutes)
    this.selectedTime = now
  }
}

7.2 时间选择器组合

@Component
struct CombinedDateTimePicker {
  @State selectedDate: Date = new Date()
  @State selectedTime: Date = new Date()

  build() {
    Column({ space: 30 }) {
      // 日期选择器(这里使用Text模拟,实际项目中可使用DatePicker)
      Text(`选择日期: ${this.selectedDate.toLocaleDateString()}`)
        .fontSize(18)
        .onClick(() => {
          // 这里可以触发日期选择器
        })

      TimePicker({
        selected: this.selectedTime
      })
      .onChange((value: Date) => {
        this.selectedTime = value
        this.updateCombinedDateTime()
      })

      Text(`完整时间: ${this.getCombinedDateTime().toLocaleString()}`)
        .fontSize(16)
        .fontColor(Color.Blue)
    }
  }

  private updateCombinedDateTime(): void {
    const combined = this.getCombinedDateTime()
    console.info('最终选择的时间:', combined.toLocaleString())
  }

  private getCombinedDateTime(): Date {
    const result = new Date(this.selectedDate)
    result.setHours(this.selectedTime.getHours())
    result.setMinutes(this.selectedTime.getMinutes())
    result.setSeconds(this.selectedTime.getSeconds())
    return result
  }
}

八、注意事项和最佳实践

8.1 重要提示

版本兼容性说明

  • TimePicker组件从API Version 8开始支持
  • useMilitaryTime属性从API Version 9开始支持
  • 请确保您的开发环境使用兼容的SDK版本

8.2 常见问题及解决方案

问题1:时间显示不正确

// ❌ 错误用法
TimePicker({
  selected: '14:30'  // 错误的数据类型
})

// ✅ 正确用法
TimePicker({
  selected: new Date()  // 必须使用Date对象
})

问题2:事件处理不当

// ❌ 避免在onChange中执行耗时操作
.onChange((value: Date) => {
  this.heavyCalculation(value) // 可能导致界面卡顿
})

// ✅ 优化方案
.onChange((value: Date) => {
  // 立即更新UI
  this.selectedTime = value
  // 异步处理复杂逻辑
  setTimeout(() => {
    this.processTimeSelection(value)
  }, 0)
})

8.3 性能优化建议

  • 避免频繁更新:在快速滚动时适当防抖
  • 内存管理:及时清理不需要的时间对象
  • 响应式设计:合理使用@State和@Prop装饰器
@Component
struct OptimizedTimePicker {
  @State selectedTime: Date = new Date()
  private updateTimer: number = 0

  build() {
    TimePicker({
      selected: this.selectedTime
    })
    .onChange((value: Date) => {
      // 防抖处理,避免频繁更新
      clearTimeout(this.updateTimer)
      this.updateTimer = setTimeout(() => {
        this.handleTimeChange(value)
      }, 100)
    })
  }

  private handleTimeChange(value: Date): void {
    this.selectedTime = value
    // 执行其他业务逻辑
  }
}

九、完整示例项目

9.1 会议预约系统

@Entry
@Component
struct MeetingScheduler {
  @State meetingTime: Date = new Date()
  @State participantCount: number = 1
  @State meetingTitle: string = ''

  build() {
    Column({ space: 25 }) {
      Text('会议预约')
        .fontSize(28)
        .fontWeight(FontWeight.Bold)

      TextInput({ placeholder: '输入会议主题' })
        .onChange((value: string) => {
          this.meetingTitle = value
        })

      TimePicker({
        selected: this.meetingTime
      })
      .useMilitaryTime(true)
      .width('90%')
      .height(200)
      .onChange((value: Date) => {
        this.meetingTime = value
      })

      Text(`会议时间: ${this.formatDisplayTime()}`)
        .fontSize(18)

      Button('确认预约')
        .onClick(() => {
          this.scheduleMeeting()
        })
        .width('80%')
    }
    .padding(20)
    .width('100%')
    .height('100%')
  }

  private formatDisplayTime(): string {
    return this.meetingTime.toLocaleTimeString('zh-CN', {
      hour: '2-digit',
      minute: '2-digit'
    })
  }

  private scheduleMeeting(): void {
    if (!this.meetingTitle) {
      promptAction.showToast({
        message: '请输入会议主题',
        duration: 2000
      })
      return
    }

    // 模拟预约逻辑
    const meetingInfo = {
      title: this.meetingTitle,
      time: this.meetingTime,
      participants: this.participantCount
    }

    console.info('会议预约成功:', meetingInfo)
    promptAction.showToast({
      message: `会议"${this.meetingTitle}"预约成功`,
      duration: 3000
    })
  }
}

总结

通过本文的学习,您应该已经掌握了:

  • ✅ TimePicker的基本创建和使用方法
  • ✅ 核心属性的配置和自定义
  • ✅ 时间变化事件的监听和处理
  • ✅ 样式自定义和主题适配
  • ✅ 实际业务场景中的应用
  • ✅ 性能优化和最佳实践

TimePicker作为HarmonyOS开发中的重要组件,合理使用可以极大提升用户体验。建议在实际开发中根据具体需求选择合适的配置方案。

进一步学习建议:

  • 探索DatePicker组件的配合使用
  • 学习国际化时间格式处理
  • 了解无障碍访问功能的实现

需要参加鸿蒙认证的请点击 鸿蒙认证链接

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐