TimePicker時間選擇器基礎設置

文章簡介

TimePicker是HarmonyOS開發中常用的時間選擇組件,本文將詳細介紹其基礎使用方法、屬性配置和實際應用場景。通過本文,您將掌握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組件的配合使用
  • 學習國際化時間格式處理
  • 瞭解無障礙訪問功能的實現

本文基於HarmonyOS 3.1版本編寫,代碼示例經過測試驗證。實際開發時請參考最新官方文檔。