在移动应用中,精确到小时和分钟的时间选择是高频需求——设置闹钟、预约提醒、安排日程都离不开时间选择器。HarmonyOS NEXT ArkUI 提供了 TimePicker 组件,以滚轮形式直观展示时间选择交互,支持时/分/秒精度配置、12/24 小时制切换和范围限制。

本文将深入讲解 TimePicker 组件的使用方法,并构建一个完整的"闹钟设置"应用——支持时间滚轮选择、闹钟创建保存、开关切换和删除管理。

关键词:HarmonyOS、ArkUI、TimePicker、时间选择器、闹钟设置、滚轮选择

一、TimePicker 组件基础

1.1 API 概述

TimePicker 是 ArkUI 提供的时间滚轮选择组件。它以垂直滚轮的形式展示时、分(可选秒),用户上下滑动滚轮选择目标时间。

TimePicker({
  selected: new Date(2026, 0, 1, 7, 0),    // 预设时间:7:00
  format: TimePickerFormat.HOUR_MINUTE      // 显示时+分
})
  .onChange((value: TimePickerResult) => {
    // value.hour: 选中的小时(0-23)
    // value.minute: 选中的分钟(0-59)
    this.selectedHour = value.hour;
    this.selectedMinute = value.minute;
  })

核心属性与回调:

  • selectedTimePickerOptions 中预设选中的时间,类型为 Date。注意:只有 hoursminutes 有效,年/月/日部分被忽略。默认值为当前系统时间
  • format:控制显示粒度。TimePickerFormat.HOUR_MINUTE(时+分,默认)或 TimePickerFormat.HOUR_MINUTE_SECOND(时+分+秒)
  • onChange(callback):用户滑动滚轮改变选中时间后触发,回调参数为 TimePickerResult 对象
  • useMilitaryTime:是否使用 24 小时制。true 显示 0-23,false 显示 AM/PM。默认为系统设置

1.2 TimePickerResult 接口

interface TimePickerResult {
  hour: number;    // 选中的小时(0-23)
  minute: number;  // 选中的分钟(0-59)
  second: number;  // 选中的秒(0-59),仅 HOUR_MINUTE_SECOND 格式有效
}

hour 始终以 24 小时制返回(0-23),无论 useMilitaryTime 设置为何。如果使用 12 小时制显示(如 “7:30 PM”),hour 仍然返回 19。这个设计保证了程序逻辑的一致性——显示格式和内部值分离。

1.3 时间范围限制

通过 startend 参数限制可选时间范围(API 18+):

TimePicker({
  selected: new Date(),
  format: TimePickerFormat.HOUR_MINUTE,
  start: new Date(2026, 0, 1, 9, 0),   // 最早 9:00
  end: new Date(2026, 0, 1, 18, 0)     // 最晚 18:00
})

超出范围的选项在滚轮上可能变灰或不可滚动。这在预约场景中非常有用——比如只允许选择工作时间的档位。

1.4 与 CalendarPicker 的配合

TimePicker 通常与 CalendarPicker 配合使用——CalendarPicker 选日期,TimePicker 选具体时间。本文 Demo 聚焦于纯时间的闹钟场景(闹钟只关心时间和重复模式,不关心具体日期),但扩展为"预约时间"时,两者组合是最常见的模式。

二、闹钟设置的整体设计

2.1 页面架构

本文 Demo 构建一个"闹钟设置"应用,模拟系统闹钟的核心体验:

AlarmPage
├── 标题栏 — "闹钟设置" + 闹钟计数
├── 组件说明卡片 — TimePicker 功能介绍
├── 消息提示区 — 操作反馈(添加/开关/删除)
├── 添加按钮 — "+ 添加闹钟"
├── TimePicker 表单(展开后)
│   ├── TimePicker — 时/分滚轮选择
│   ├── 闹钟标签 TextInput
│   ├── 取消按钮
│   └── 保存按钮
└── 闹钟列表
    ├── 时间 + 标签展示
    ├── ON/OFF 开关
    └── 删除按钮

2.2 数据结构

interface AlarmItem {
  id: number;
  hour: number;        // 0-23
  minute: number;      // 0-59
  label: string;       // 闹钟名称
  enabled: boolean;    // 是否开启
  repeat: boolean[];   // 周几重复([一,二,三,四,五,六,日])
}

repeat 是一个 7 元素布尔数组,对应周一到周日。全部 false 表示"不重复"(单次闹钟),全部 true 表示"每天",周一到周五 true 表示"工作日"。

2.3 时间格式化

闹钟列表中的时间以 HH:MM 格式显示:

formatTime(h: number, m: number): string {
  return h.toString().padStart(2, '0')
    .concat(':')
    .concat(m.toString().padStart(2, '0'));
}

padStart(2, '0') 确保个位数前补零——7:05 显示为 “07:05” 而非 “7:5”。数字时钟的视觉一致性要求所有时间显示的位数一致。
在这里插入图片描述

三、TimePicker 在闹钟设置中的应用

3.1 展开添加表单

点击"+ 添加闹钟"按钮,TimePicker 表单在按钮下方展开:

showAddAlarm(): void {
  this.pickHour = 7;
  this.pickMinute = 0;
  this.pickLabel = '';
  this.showPicker = true;
  this.message = '';
}

默认时间设为早上 7:00——这是一个用户体验决策:大多数用户的第一个闹钟设置在早上 7 点左右,默认靠近这个时间可以减少滚轮滑动次数。

3.2 TimePicker 配置

TimePicker({
  selected: new Date(2026, 0, 1, this.pickHour, this.pickMinute),
  format: TimePickerFormat.HOUR_MINUTE
})
  .onChange((value: TimePickerResult) => {
    this.onTimeChange(value);
  })

format 使用 HOUR_MINUTE——闹钟场景不需要秒级精度。selected 中的年/月/日(2026, 0, 1)仅作为占位符,实际有效的只有 hourminute

3.3 保存闹钟

saveAlarm(): void {
  let newAlarm: AlarmItem = {
    id: this.nextId,
    hour: this.pickHour,
    minute: this.pickMinute,
    label: this.pickLabel.trim().length > 0 ? this.pickLabel.trim() : '闹钟',
    enabled: true,
    repeat: [false, false, false, false, false, false, false]
  };
  this.nextId++;
  this.alarms = [newAlarm].concat(this.alarms.slice());
  this.showPicker = false;
}

新闹钟默认开启(enabled: true),默认不重复(repeatfalse)。[newAlarm].concat(this.alarms.slice()) 将新闹钟插入列表头部(最新的在上面)。

标签如果为空则默认显示"闹钟"——这是一个友好的兜底策略,避免空白标签。
在这里插入图片描述

四、闹钟管理功能

4.1 开关切换

每个闹钟卡片有一个 ON/OFF 开关按钮:

toggleAlarm(id: number): void {
  let idx = -1;
  for (let i = 0; i < this.alarms.length; i++) {
    if (this.alarms[i].id === id) { idx = i; break; }
  }
  if (idx < 0) return;
  let updated = this.alarms.slice();
  updated[idx] = {
    id: updated[idx].id,
    hour: updated[idx].hour,
    minute: updated[idx].minute,
    label: updated[idx].label,
    enabled: !updated[idx].enabled,  // 翻转开关状态
    repeat: updated[idx].repeat
  };
  this.alarms = updated;
}

ArkTS 的 @State 要求数组元素修改也必须创建新对象。所以不能直接 this.alarms[idx].enabled = ...,需要完整地展开并替换整个元素。这是 ArkUI 响应式系统最需要适应的"额外步骤"——但换来的好处是 UI 状态的可预测性强,不会有"改了一部分 UI 没更新"的 bug。

4.2 删除闹钟

deleteAlarm(id: number): void {
  this.alarms = this.alarms.slice()
    .filter((a: AlarmItem) => a.id !== id);
}

标准的 slice + filter 模式。删除后的消息反馈"闹钟已删除"通过 showMessage 显示在顶部的临时消息区域。

4.3 消息反馈

操作完成后,顶部消息栏短暂显示反馈:

showMessage('闹钟已添加 — 07:30')
showMessage('已开启 — 08:00')
showMessage('闹钟已删除')

消息是瞬时的——下次操作会覆盖上一条消息。在实际应用中,消息栏可能会增加一个自动消失的定时器(2-3 秒后自动清空),避免长时间占用屏幕空间。

五、重复模式

5.1 智能识别

getRepeatText 方法将 boolean[] 数组转换为人类可读的重复描述:

getRepeatText(r: boolean[]): string {
  if (r.every(v => !v)) return '不重复';           // 全 false
  if (r.every(v => v)) return '每天';              // 全 true
  // 工作日:周一到周五 true,周六日 false
  if (r.slice(0,5).every(v => v) && !r[5] && !r[6]) return '工作日';
  // 周末:周六日 true,周一到周五 false
  if (!r[0] && !r[1] && !r[2] && !r[3] && !r[4] && r[5] && r[6]) return '周末';
  // 自定义:列出每个选中的星期
  return ['一','二','三','四','五','六','日']
    .filter((_, i) => r[i]).join('、');
}

这个函数展示了"模式匹配"的逻辑分层:

  1. 先匹配最简单的全否/全是
  2. 再匹配常见的预设组合(工作日、周末)
  3. 最后回退到逐项列举

匹配顺序很重要——"工作日"也是"周一、周二、周三、周四、周五"的子集,但应该优先匹配为预设名称而非逐项列举。

六、视觉设计

6.1 闹钟卡片的状态表达

闹钟卡片根据 enabled 状态改变视觉效果:

  • 开启:时间文字黑色(#1a1a2e),标签灰色(#9999AA),开关按钮蓝色
  • 关闭:所有文字变灰(#CCCCDD),开关按钮灰色

这种"整体灰化"的设计比仅改变开关按钮颜色更直观——用户扫一眼列表就能看到哪些闹钟是开启的,不需要逐个检查开关状态。

6.2 空状态

当没有任何闹钟时,显示空状态引导:

⏰
暂无闹钟
点击上方按钮添加第一个闹钟

空状态不是简单的"无数据"——它包含图标(建立隐喻)、状态说明(告知当前情况)和行动指引(明确下一步操作)。

七、交互流程演示

7.1 添加第一个闹钟

进入页面,列表为空,显示空状态。点击"+ 添加闹钟",TimePicker 表单展开,默认显示 07:00。滑动滚轮调整到 08:30,输入标签"上班闹钟",点击"保存闹钟"。表单关闭,列表中出现第一条闹钟(开启状态,蓝色开关)。

7.2 添加更多闹钟

再次点击"+ 添加闹钟",设置 12:00,标签"午餐",保存。再添加 18:00,标签"健身",保存。列表已有 3 条闹钟。

7.3 关闭闹钟

点击"午餐"闹钟的 ON 按钮,开关变为灰色 OFF,整个卡片文字变灰。

7.4 删除闹钟

点击"健身"闹钟的"删除"按钮,该闹钟从列表中消失,提示"闹钟已删除"。列表中剩余 2 条闹钟。

八、总结

本文通过"闹钟设置"这个实战案例,全面讲解了 ArkUI TimePicker 组件的使用方法。核心知识点包括:

  1. TimePicker API:selected、format(HOUR_MINUTE/HOUR_MINUTE_SECOND)、onChange
  2. TimePickerResult:hour(0-23)、minute(0-59)字段
  3. 闹钟管理:添加(concat 头部插入)、删除(filter)、开关切换(slice + 新对象替换)
  4. @State 响应式规则:数组元素修改必须创建完整新对象
  5. UI 状态表达:enabled 控制卡片整体灰化 + 开关颜色
  6. 重复模式智能识别:全否→不重复、全是→每天、工作日→周末→逐项列举

TimePicker 组件将"时间选择"这个复杂的滚轮交互封装为简洁的 API——开发者不需要处理滚轮惯性的物理计算,不需要处理时间上下溢(如分钟从 59 滚到 0),不需要处理 12/24 小时制的格式转换。组件的内部机制保证了时间始终处于有效范围,开发者只需在 onChange 回调中捕获 hourminute 并更新业务状态。


Logo

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

更多推荐