TimePicker
时间选择器,按 min / maxTime 逐级收窄时分秒
时间选择器(TimePicker)在 Picker 之上把时、分、秒三列的级联范围算好。TimePickerView 是内联滚轮,TimePicker 把它装进底部弹层并采用「确定才提交」的语义。列由 columnsType 与 minTime / maxTime 推导,因此 columns 与 fieldNames 不再对外开放。
import { TimePicker, TimePickerView } from '@skyroc/native-ui';TimePicker 依赖 @gorhom/bottom-sheet,请确保 App 根节点已经包了 GestureHandlerRootView 与 BottomSheetModalProvider。
基础用法
默认只显示时、分两列。不传 defaultValue 时滚轮停在当前时刻(而不是区间开头),并且初值同样会过一遍钳位 —— minTime / maxTime 把此刻排除在外时,开局就不会拿一个越界值去渲染。
import { TimePickerView } from '@skyroc/native-ui';
import { View } from 'react-native';
const TimePickerBasic = () => {
return (
<View className="bg-background px-6 py-4">
<TimePickerView showToolbar={false} />
</View>
);
};
export { TimePickerBasic };选中值沿用 Picker 的 string[],每一项是补零后的两位数字(如 ['09', '30']),顺序与 columnsType 一致。
何时使用
- 只选时间点(闹钟、营业时间、预约时段)。
- 选日期或日期 + 时间请用
DatePicker;两者都要且要分步填,用PickerGroup把它们放进不同 tab。
限制可选区间
minTime / maxTime 的格式是 "HH:mm:ss",默认 "00:00:00" ~ "23:59:59"。缺省的段按 0 补("09" 等于 09:00:00),非法段也落回 0 而不是抛错 —— 这两个值通常是手写字符串,一个笔误不该把整个滚轮打空。上界早于下界时会退化成下界那一个时刻。
import { TimePickerView } from '@skyroc/native-ui';
import { View } from 'react-native';
const TimePickerLimit = () => {
return (
<View className="bg-background px-6 py-4">
<TimePickerView
showToolbar={false}
defaultValue={['08', '00']}
maxTime="18:15:00"
minTime="09:30:00"
/>
</View>
);
};
export { TimePickerLimit };收窄是逐级的:分列只有停在首尾小时上时才受限(minTime 是 09:30 时,停在 09 点分列从 30 起,停在中间的整点仍是 00–59)。
时分秒三列
columnsType 决定显示哪几列及其顺序,默认 ['hour', 'minute']。
import { TimePickerView } from '@skyroc/native-ui';
import { View } from 'react-native';
const TimePickerColumns = () => {
return (
<View className="bg-background px-6 py-4">
<TimePickerView
columnsType={['hour', 'minute', 'second']}
showToolbar={false}
maxTime="12:00:30"
minTime="10:00:00"
/>
</View>
);
};
export { TimePickerColumns };秒列只有时、分同时停在首尾上时才会被收窄。columnsType 允许不含 hour(只显示分秒),这时缺的那一段用挂载时快照的当前时刻补位。
列与选中值互相牵制,组件会迭代到不动点:时被钳到首尾小时上之后,分列的上下界才跟着收窄,秒列还要再跟一轮。只算一轮的话,maxTime 是 10:30 而传进来 11:45 时,会得到一个越界的 10:45。
格式化与过滤
formatter(type, option):只改显示文本,不改值(例如给数字补上「时」「分」「秒」)。filter(type, options, values):挖掉候选项本身(例如分钟只留整五分)。
import { TimePickerView } from '@skyroc/native-ui';
import type { TimePickerFilter, TimePickerFormatter as TimePickerFormatterType } from '@skyroc/native-ui';
import { View } from 'react-native';
/** 各列的中文单位 */
const COLUMN_UNITS = { hour: '时', minute: '分', second: '秒' };
/** 给数字列补上中文单位 */
const CN_FORMATTER: TimePickerFormatterType = (type, option) => ({
...option,
label: `${option.label}${COLUMN_UNITS[type]}`
});
/** 分钟只留整五分,用来验证 filter 把中间值挖空后选中值会落到最近的可选项 */
const STEP_MINUTE_FILTER: TimePickerFilter = (columnType, options) => {
if (columnType !== 'minute') return options;
return options.filter(option => Number.parseInt(option.value ?? '0', 10) % 5 === 0);
};
const TimePickerFormatter = () => {
return (
<View className="bg-background px-6 py-4">
<TimePickerView
filter={STEP_MINUTE_FILTER}
formatter={CN_FORMATTER}
showToolbar={false}
/>
</View>
);
};
export { TimePickerFormatter };被 filter 挖空的选中值会落到最接近的可选项,而不是被弹到列尾。
弹层用法
TimePicker 与 Picker 的提交语义一致:滚动中的值是临时的,点确定才写回 value 并触发 onConfirm,取消直接丢弃。注意 onChange 在这里挂的是已确认值(与内联的 TimePickerView 不同,后者滚动即触发)。
import { Button, Text, TimePicker } from '@skyroc/native-ui';
import type { TimePickerFilter } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';
/** 分钟只留整五分,用来验证 filter 把中间值挖空后选中值会落到最近的可选项 */
const STEP_MINUTE_FILTER: TimePickerFilter = (columnType, options) => {
if (columnType !== 'minute') return options;
return options.filter(option => Number.parseInt(option.value ?? '0', 10) % 5 === 0);
};
const TimePickerPopup = () => {
const [meetingShow, setMeetingShow] = useState(false);
const [meeting, setMeeting] = useState<string[]>([]);
const meetingLabel = meeting.length > 0 ? meeting.join(':') : '请选择';
return (
<View className="flex-row flex-wrap items-center gap-3 bg-background px-6 py-4">
<Button
variant="tonal"
onPress={() => setMeetingShow(true)}
>
选择会议时间
</Button>
<Text color="muted">当前:{meetingLabel}</Text>
<TimePicker
show={meetingShow}
title="会议时间"
value={meeting}
filter={STEP_MINUTE_FILTER}
maxTime="18:00:00"
minTime="09:00:00"
onConfirm={setMeeting}
onUpdateShow={setMeetingShow}
/>
</View>
);
};
export { TimePickerPopup };同样地,滚轮独占垂直手势,面板的内容拖拽是关掉的,enablePanDownToClose 需要配合 showHandle。
自定义触发元素
children 传渲染函数即可自己画触发元素,参数为 { open, value },value 是已确认值。
import { Cell, TimePicker } from '@skyroc/native-ui';
import type { TimePickerFormatter } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';
/** 各列的中文单位 */
const COLUMN_UNITS = { hour: '时', minute: '分', second: '秒' };
/** 给数字列补上中文单位 */
const CN_FORMATTER: TimePickerFormatter = (type, option) => ({
...option,
label: `${option.label}${COLUMN_UNITS[type]}`
});
const TimePickerTrigger = () => {
const [alarmShow, setAlarmShow] = useState(false);
const [alarm, setAlarm] = useState<string[]>(['07', '30']);
const alarmLabel = alarm.length > 0 ? alarm.join(':') : '请选择';
return (
<View className="bg-background px-6 py-4">
<TimePicker
formatter={CN_FORMATTER}
show={alarmShow}
title="设置闹钟"
value={alarm}
onConfirm={setAlarm}
onUpdateShow={setAlarmShow}
>
{args => (
<Cell
showArrow
title="起床闹钟"
trailing={alarmLabel}
onPress={args.open}
/>
)}
</TimePicker>
</View>
);
};
export { TimePickerTrigger };API
TimePickerView
除下表外,TimePickerView 继承 PickerView 的属性(value / defaultValue / itemHeight / visibleCount / haptic / loading / showToolbar / title / cancelText / confirmText / onCancel / onConfirm / className / classNames),其中 columns 与 fieldNames 被移除。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| columnsType | 显示哪几列及其顺序 | ('hour' | 'minute' | 'second')[] | ['hour', 'minute'] |
| minTime | 可选的最小时刻,格式 "HH:mm:ss",缺省的段按 0 补 | string | '00:00:00' |
| maxTime | 可选的最大时刻,格式 "HH:mm:ss";早于 minTime 时退化成 minTime 那一刻 | string | '23:59:59' |
| formatter | 定制选项的显示文本,不改变值 | TimePickerFormatter | - |
| filter | 从某一列里剔除选项 | TimePickerFilter | - |
| defaultValue | 非受控初始值,缺省时取当前时刻并按区间钳位 | string[] | - |
| value | 选中值(受控),每列一个补零后的两位数字 | string[] | - |
| onChange | 选中值变化时触发,滚动过程中即触发 | (values: string[]) => void | - |
TimePicker
TimePicker 继承 TimePickerView 的属性;value 表示已确认值,onChange 只在提交后触发。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| show* | 是否显示弹层 | boolean | - |
| onUpdateShow | 显示状态变化回调 | (show: boolean) => void | - |
| onChange | 已确认值变化的回调;面板内滚动不触发 | (values: string[]) => void | - |
| children | 触发元素:节点会被包一层 Pressable,渲染函数可拿到 open 与已确认 value | ReactNode | ((params: { open: () => void; value: string[] }) => ReactNode) | - |
| closeOnBackdropPress | 点击遮罩是否关闭 | boolean | true |
| showHandle | 是否显示面板顶部的拖拽指示条 | boolean | false |
| enablePanDownToClose | 是否允许下拉关闭,需要同时开启 showHandle 才有可拖之处 | boolean | false |
| sheetClassName | 内部 Sheet 面板本体的类名(className 给的是滚轮那块) | string | - |
| sheetClassNames | 内部 Sheet 各 slot 的类名覆盖 | SlotClassNames<SheetSlots> | - |
| ref | 底层 BottomSheetModal 的实例引用,用于 dismiss / snapToIndex / expand 等命令式操作 | Ref<BottomSheetModal> | - |
类型
import type {
TimePickerColumnType,
TimePickerFilter,
TimePickerFormatter,
TimePickerProps,
TimePickerViewProps
} from '@skyroc/native-ui';TimePickerColumnType
时间列的类型标识,同时决定 columnsType 的取值。
TimePickerFormatter
定制某一列选项的显示文本,返回新的选项对象;只改 label,不改 value。
TimePickerFilter
从某一列里剔除选项,第三个参数是当前各列的选中值。
SlotClassNames
classNames 的取值形态:把 slot 名映射到类名,每个 slot 都可选。本组件的 slot 沿用 PickerSlots。