时间选择是移动应用中继日期选择之后的第二高频时间交互。HarmonyOS NEXT ArkUI 提供了 TimePicker 组件,以经典的两列滚轮(时/分)交互模式让用户快速选定时间。与 DatePicker 的年月日三级滚轮不同,TimePicker 专注于时和分的选择,交互更加简洁直接。

本文将深入讲解 TimePicker 的 API 设计和使用方法,并通过一个完整的"闹钟模拟器"实战案例,展示 12/24 小时制切换、剩余时间倒计时、标签命名和快捷时间预设等功能。

关键词:HarmonyOS、ArkUI、TimePicker、时间选择、闹钟、倒计时

一、TimePicker 组件概览

TimePicker 采用两列滚轮式交互——左列是小时(0-23),右列是分钟(0-59)。与 DatePicker 相比,TimePicker 少了"天"的维度,使用户能更快速地选择精确到分钟的时间点。

它的典型应用场景包括:

  • 闹钟设置(选择提醒时间)
  • 预约时段(选择开始时间)
  • 提醒设定(选择通知触发时间)
  • 倒计时起始时间选择

结合 DatePicker 和 TextClock,这三个组件构成了 ArkUI 时间相关组件体系的完整拼图。

二、TimePicker 核心 API

2.1 构造函数

TimePicker({
  selected: Date  // 初始选中的时间
})

TimePicker 的构造函数只有一个参数 selected,接受一个 JavaScript Date 对象。组件会自动从 Date 对象中提取时和分,忽略年、月、日部分。

// 默认选中早上 7:00
TimePicker({
  selected: new Date(2026, 0, 1, 7, 0)
})

2.2 onChange 回调与 TimePickerResult

当用户滑动滚轮改变选中时间时,onChange 被触发,返回 TimePickerResult 对象:

interface TimePickerResult {
  hour: number;    // 0-23(始终为 24 小时制)
  minute: number;  // 0-59
}

值得注意的重要设计:hour 始终是 24 小时制(0-23),无论页面上是否启用了 12 小时制显示。这意味着 TimePicker 的内部数据模型是纯粹的 24 小时制,12 小时制的 AM/PM 显示完全由应用层负责转换。这种设计让数据与显示分离,避免了"上午 7 点"和"下午 7 点"(19 点)在数据层上的歧义。

TimePicker({ selected: new Date(2026, 0, 1, 7, 0) })
  .onChange((value: TimePickerResult) => {
    this.alarmHour = value.hour!;    // 7(24h 制)
    this.alarmMinute = value.minute!;
  })

2.3 关键属性

属性 类型 说明
.useMilitaryTime() - 强制 24 小时制显示
.loop() boolean 是否循环滚动
.disappearTextStyle() PickerTextStyle 非选中项文字样式
.selectedTextStyle() PickerTextStyle 选中项文字样式
!

在这里插入图片描述

三、12/24 小时制转换

TimePicker 内部使用 24 小时制存储小时值,但很多场景需要展示 12 小时制(带 AM/PM)。我们需要在应用层实现转换逻辑:

// 24h → 12h 数字
fmt12h(h: number): string {
  const h12 = h % 12;
  if (h12 === 0) return '12';  // 0点→12点, 12点→12点
  return h12.toString();
}

// 判断上午/下午
ampm(h: number): string {
  return h < 12 ? '上午' : '下午';
}

// 格式化完整时间字符串
fmtTimeString(): string {
  if (this.use24h) {
    return this.alarmHour.toString().padStart(2, '0')
      .concat(':', this.alarmMinute.toString().padStart(2, '0'));
  }
  return this.ampm(this.alarmHour).concat(' ',
    this.fmt12h(this.alarmHour), ':',
    this.alarmMinute.toString().padStart(2, '0'));
}

三个关键转换规则:

  1. 0 点 在 12 小时制中显示为 12:00(午夜)
  2. 12 点 在 12 小时制中显示为 12:00(正午)
  3. 13-23 点 对 12 取模得到 1-11,且标注为"下午"
    在这里插入图片描述

四、实战:闹钟模拟器

我们实现一个完整的闹钟模拟器,核心功能包括:

  1. TimePicker 时间选择:两列滚轮选择时和分
  2. 12/24 时制切换:Toggle 开关控制显示格式
  3. 闹钟标签命名:TextInput 自定义闹钟名称
  4. 剩余时间倒计时:设定后实时显示距闹钟响铃还有多久
  5. 快捷时间预设:8 个常用时间一键设定

4.1 核心状态

@State alarmHour: number = 7;      // 0-23
@State alarmMinute: number = 0;
@State use24h: boolean = true;     // 时制开关
@State alarmLabel: string = '起床闹钟';
@State alarmActive: boolean = false; // 闹钟是否已设定
@State remainText: string = '';    // 剩余时间文字

4.2 剩余时间计算

设定闹钟后,需要计算当前时间与闹钟时间的差值。核心逻辑是:如果闹钟时间已过,则自动推到明天同一时间。

updateRemain(): void {
  if (!this.alarmActive) {
    this.remainText = '未设置';
    return;
  }
  const now = new Date();
  let alarm = new Date(
    now.getFullYear(), now.getMonth(), now.getDate(),
    this.alarmHour, this.alarmMinute, 0
  );
  // 如果闹钟时间已过,推到明天
  if (alarm.getTime() <= now.getTime()) {
    alarm = new Date(alarm.getTime() + 24 * 60 * 60 * 1000);
  }
  // 计算小时和分钟差
  const diff = alarm.getTime() - now.getTime();
  const h = Math.floor(diff / (1000 * 60 * 60));
  const m = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
  this.remainText = '还有 '.concat(h.toString(), ' 小时 ', m.toString(), ' 分钟');
}

为了保持剩余时间更新,设定闹钟后开启一个定时器每分钟刷新:

setAlarm(): void {
  this.alarmActive = true;
  this.updateRemain();
  if (this.intervalId !== -1) {
    clearInterval(this.intervalId);
  }
  // 每 30 秒刷新剩余时间
  this.intervalId = setInterval(() => { this.updateRemain(); }, 30000);
}

页面销毁时记得清理定时器:

aboutToDisappear(): void {
  if (this.intervalId !== -1) {
    clearInterval(this.intervalId);
  }
}

4.3 快捷时间预设

提供 8 个常用闹钟时间的快捷按钮,覆盖从早到晚的典型场景:

Row() {
  this.QuickBtn('06:30', 6, 30)
  this.QuickBtn('07:00', 7, 0)
  this.QuickBtn('07:30', 7, 30)
  this.QuickBtn('08:00', 8, 0)
}
Row() {
  this.QuickBtn('12:00', 12, 0)
  this.QuickBtn('14:00', 14, 0)
  this.QuickBtn('18:30', 18, 30)
  this.QuickBtn('22:00', 22, 0)
}

QuickBtn 使用 @Builder 提取为独立方法:

@Builder
QuickBtn(label: string, h: number, m: number) {
  Text(label)
    .fontSize(13).fontColor('#1677FF').fontWeight(FontWeight.Medium)
    .padding({ top: 8, bottom: 8, left: 14, right: 14 })
    .borderRadius(10).backgroundColor('#EEF3FF').margin({ right: 8 })
    .onClick(() => {
      this.alarmHour = h;
      this.alarmMinute = m;
      if (this.alarmActive) { this.updateRemain(); }
    })
}

4.4 时间显示区域

一个醒目的时间展示卡片,使用大号等宽字体显示当前设定的闹钟时间:

Row() {
  Text('⏰').fontSize(36).margin({ right: 14 })
  Column() {
    Text(this.fmtTimeString())
      .fontSize(40).fontColor('#1a1a2e').fontWeight(FontWeight.Bold)
      .fontFamily('monospace').margin({ bottom: 6 })
    Text(this.alarmActive ? '闹钟已开启' : '闹钟未开启')
      .fontSize(12)
      .fontColor(this.alarmActive ? '#52C41A' : '#9999AA')
  }
}

如果闹钟已设定,额外显示一个橙色的剩余时间标签,让用户一目了然地知道距离闹钟触发还有多久。

4.5 设定/取消按钮

按钮在不同状态下有完全不同的外观和行为:

  • 未设定状态:蓝色按钮,文字"设定闹钟"
  • 已设定状态:红色按钮,文字"取消闹钟"
if (!this.alarmActive) {
  Button('设定闹钟')
    .fontSize(16).fontColor('#FFFFFF').fontWeight(FontWeight.Bold)
    .width('100%').height(48).borderRadius(24)
    .backgroundColor('#1677FF')
    .onClick(() => { this.setAlarm(); })
} else {
  Button('取消闹钟')
    .fontSize(16).fontColor('#FFFFFF').fontWeight(FontWeight.Bold)
    .width('100%').height(48).borderRadius(24)
    .backgroundColor('#FF4D4F')
    .onClick(() => { this.cancelAlarm(); })
}

五、与其他时间组件的配合

TimePicker 很少单独使用,它通常与 DatePicker、TextClock、TextTimer 配合构成完整的时间交互方案:

组合 场景 说明
DatePicker + TimePicker 预约/日程 先选日期再选时间
TimePicker + TextClock 闹钟 设置时间 + 显示当前时间
TimePicker + TextTimer 倒计时 选定截止时间 + 倒计时显示

例如,一个完整的"预约提醒"功能可能需要:DatePicker 选日期 → TimePicker 选时间 → TextTimer 显示剩余时间。这三个组件的组合能覆盖绝大部分时间相关的交互需求。

六、完整交互流程

  1. 初始状态:TimePicker 显示 07:00,时间卡片显示"07:00",闹钟未设定
  2. 选择时间:滑动时和分滚轮,时间卡片实时同步更新显示的时间
  3. 切换时制:关闭"24 小时制"开关,显示变为"上午 7:00"
  4. 命名标签:在输入框中输入"晨会提醒"
  5. 快捷设定:点击"08:00"快捷按钮,时间跳转到 8:00
  6. 设定闹钟:点击蓝色"设定闹钟"按钮,剩余时间开始计算并显示
  7. 取消闹钟:点击红色"取消闹钟"按钮,回到未设定状态

七、总结

TimePicker 是 ArkUI 时间组件家族中"小而精"的一员。它的 API 极简——只有一个 selected 参数和一个 onChange 回调——但配合应用层的 12/24 时制转换和时间计算逻辑,可以构建出功能完备的闹钟应用。

本文通过"闹钟模拟器"这个实战案例,覆盖了:

  1. TimePicker 的基本用法和 TimePickerResult 接口
  2. 12/24 小时制的应用层转换逻辑(三个关键规则)
  3. 剩余时间的跨天计算(已过时间自动推到明天)
  4. 快捷时间预设的 @Builder 复用
  5. 定时器的生命周期管理(aboutToDisappear 清理)

TimePicker 配合 DatePicker 和 TextTimer,三者共同构成了鸿蒙应用中时间选择与管理的完整能力矩阵。掌握了 TimePicker,你就补全了时间交互的最后一块拼图。


Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐