@hxa-rn/react-native-multi-wheel-picker
v1.0.0
Published
react-native-multi-wheel-picker for HarmonyOS
Readme
react-native-multi-wheel-picker
本项目基于 @quidone/react-native-wheel-picker 开发,并适配 React Native for OpenHarmony。 如果在使用过程中有任何问题,可以在 GitCode 提交 Issue,我们会及时跟进。
项目介绍
react-native-multi-wheel-picker 是一个用于从选项列表中选取单个值的 React Native 选择器组件库,已完成 React Native for OpenHarmony 适配。该模块为纯 JavaScript/TypeScript 实现,不包含 C++、ArkTS 或 HAR 原生模块。
主要能力包括:
WheelPicker:通用滚轮选择器,支持自定义数据源、选项渲染、容器与中心高亮覆盖层。DatePicker:年、月、日联动日期选择器,支持本地化与可选日期范围限制。Picker Control:通过usePickerControl、withPickerControl等实现多选择器状态协同与事件监听。withVirtualized:基于Animated.FlatList的大数据量虚拟化渲染。usePickerItemHeight、useScrollContentOffset等辅助 Hook。
集成指南
安装
在 React Native 工程根目录执行:
npm install @hxa-rn/react-native-multi-wheel-picker本库要求宿主工程满足以下 peer dependency:
react-native >=0.72react >=16.8
Autolinking
本库为纯 JavaScript/TypeScript 实现,不包含 C++、ArkTS 或 HAR 原生模块,安装后无需任何 Autolinking 配置,也无需在 oh-package.json5、PackageProvider 或 ArkTS 中注册。
导入
import WheelPicker, {
DatePicker,
usePickerControl,
withPickerControl,
useOnPickerValueChangingEffect,
useOnPickerValueChangedEffect,
withVirtualized,
usePickerItemHeight,
useScrollContentOffset,
} from '@hxa-rn/react-native-multi-wheel-picker';入口默认导出 WheelPicker,并导出 DatePicker、withVirtualized 以及上述控制器和 Hook;同时导出 PickerItem、WheelPickerProps、ValueChangingEvent、ValueChangedEvent 等类型。
使用说明
基础用法
import React, {useState} from 'react';
import WheelPicker, {type PickerItem} from '@hxa-rn/react-native-multi-wheel-picker';
const data: PickerItem<string>[] = [
{value: 'beijing', label: '北京'},
{value: 'shanghai', label: '上海'},
{value: 'guangzhou', label: '广州'},
];
export function CityPicker() {
const [value, setValue] = useState('beijing');
return (
<WheelPicker
data={data}
value={value}
itemHeight={48}
visibleItemCount={5}
onValueChanged={({item}) => setValue(item.value)}
/>
);
}onValueChanging 在滚动过程中触发,onValueChanged 在滚动结束、最终选项确定后触发,两者均接收 {item, index}。WheelPicker 是受控组件,value 应始终与 data 中某个数据项的 value 对应。
日期选择器
import React, {useState} from 'react';
import {DatePicker} from '@hxa-rn/react-native-multi-wheel-picker';
export function BirthdayPicker() {
const [date, setDate] = useState('2025-06-15');
return (
<DatePicker
date={date}
minDate="2020-01-01"
maxDate="2030-12-31"
locale="zh-CN"
onDateChanged={({date: nextDate}) => setDate(nextDate)}
/>
);
}locale 控制年、月、日的排列顺序与月份名称:zh-CN 按年-月-日显示,en-US 按月-日-年显示。变更年月时组件会自动修正日期,以保证其有效且位于可选范围内。
多选择器联动
使用 usePickerControl 创建控制器,并通过 withPickerControl 包装 WheelPicker。同一控制器中的选择器在停止滚动后会统一触发控制器的完成事件。
import React, {useState} from 'react';
import WheelPicker, {
usePickerControl,
useOnPickerValueChangedEffect,
withPickerControl,
} from '@hxa-rn/react-native-multi-wheel-picker';
const ControlledPicker = withPickerControl(WheelPicker);
const provinces = [
{value: 'gd', label: '广东省'},
{value: 'zj', label: '浙江省'},
];
export function LinkedPicker() {
const control = usePickerControl();
const [province, setProvince] = useState('gd');
useOnPickerValueChangedEffect(control, ({pickers}) => {
console.info('所有选择器停止滚动:', pickers);
});
return (
<ControlledPicker
control={control}
pickerName="province"
data={provinces}
value={province}
onValueChanged={({item}) => setProvince(item.value)}
/>
);
}大数据量虚拟化
对数据量较大的选择器使用 withVirtualized 包装。包装后的组件额外支持 initialNumToRender、maxToRenderPerBatch、windowSize 与 updateCellsBatchingPeriod 等 FlatList 虚拟化参数。
import React, {useState} from 'react';
import WheelPicker, {withVirtualized} from '@hxa-rn/react-native-multi-wheel-picker';
const VirtualizedPicker = withVirtualized(WheelPicker);
const data = Array.from({length: 1000}, (_, index) => ({
value: index,
label: `选项 ${index + 1}`,
}));
export function LargeDataPicker() {
const [value, setValue] = useState(0);
return (
<VirtualizedPicker
data={data}
value={value}
initialNumToRender={10}
windowSize={5}
onValueChanged={({item}) => setValue(item.value)}
/>
);
}接口文档
以下 API 依据 src/index.tsx、src/base/picker/Picker.tsx 及相关类型定义整理。
WheelPicker
通用滚轮选择器,是本库的默认导出组件。通过 data 提供选项、value 控制当前选中项,并支持自定义列表、选项、容器与中心高亮覆盖层的渲染。
| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| data | ReadonlyArray<PickerItem<T>> | - | 数据源;PickerItem 至少包含 value,可选 label。 |
| value | T | - | 当前选中项的值。 |
| extraValues | unknown[] | [] | 额外关联值,主要由 Picker Control 内部使用。 |
| itemHeight | number | 48 | 单个选项的高度。 |
| visibleItemCount | number | 5 | 可见选项数量,须为大于 0 的奇数。 |
| width | number \| 'auto' \| \${number}%`|'auto'| 选择器宽度。 |
|readOnly|boolean|false| 是否禁止滚动。 |
|enableScrollByTapOnItem|boolean| - | 点击非中心选项时是否滚动到中心。 |
|onValueChanging|(event) => void| - | 滚动过程中的值变化回调。 |
|onValueChanged|(event) => void| - | 滚动结束后的值变化回调。 |
|keyExtractor|(item, index) => string|index.toString()| 数据项键生成函数。 |
|renderItem|(props) => ReactElement | null| 默认文本项 | 自定义选项内容。 |
|renderItemContainer|(props) => ReactElement| 默认容器 | 自定义选项容器与点击行为。 |
|renderOverlay|(props) => ReactElement | null| 默认高亮框 | 自定义中心高亮层;传入null可隐藏。 |
|renderList|(props) => ReactElement| 默认列表 | 自定义底层滚动列表。 |
|style|StyleProp| - | 选择器根容器样式。 |
|itemTextStyle|StyleProp| - | 默认选项文本样式。 |
|overlayItemStyle|StyleProp| - | 默认中心高亮层样式。 |
|contentContainerStyle|StyleProp| - | 滚动内容容器样式。 |
|scrollEventThrottle|number| - | 透传给底层滚动列表的滚动事件节流值。 |
|disableIntervalMomentum|boolean| - | 是否禁用按项吸附后的惯性滚动。 |
|testID|string` | - | 测试标识。 |
事件与类型
type PickerItem<T> = {
value: T;
label?: string;
} & Record<string, any>;
type ValueChangingEvent<T> = {
item: PickerItem<T>;
index: number;
};
type ValueChangedEvent<T> = {
item: PickerItem<T>;
index: number;
};包入口还导出 OnValueChanging、OnValueChanged、WheelPickerProps,以及自定义渲染相关的 RenderItemProps、RenderItemContainerProps、RenderOverlayProps、RenderListProps 等类型。
DatePicker
年、月、日联动日期选择器,内部由三个 WheelPicker 组成。
| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| date | string | - | 当前日期,格式为 YYYY-MM-DD。 |
| onDateChanged | ({date}) => void | - | 日期变更回调,返回格式化后的日期字符串。 |
| minDate | string | - | 最小可选日期,格式为 YYYY-MM-DD。 |
| maxDate | string | - | 最大可选日期,格式为 YYYY-MM-DD。 |
| locale | string | 'en' | 日期单元顺序和月份名称的本地化配置。 |
| renderDate | () => ReactNode | 内置日选择器 | 自定义日选择器。 |
| renderMonth | () => ReactNode | 内置月选择器 | 自定义月选择器。 |
| renderYear | () => ReactNode | 内置年选择器 | 自定义年选择器。 |
| children | ({dateNodes}) => ReactNode | 按本地化顺序渲染 | 自定义年、月、日选择器的布局。 |
| itemHeight、visibleItemCount、readOnly 等 | 与 WheelPicker 相同 | - | 作为公共属性传给年、月、日三个内部滚轮。 |
| pickerStyle | StyleProp<ViewStyle> | - | 三个内部滚轮的根容器样式。 |
控制器、HOC 与 Hook
| 接口 | 说明 |
| --- | --- |
| usePickerControl() | 创建并保持一个选择器控制器实例。 |
| withPickerControl(WheelPicker) | 返回受控制器管理的选择器;需额外传入 control 和唯一的 pickerName。 |
| useOnPickerValueChangingEffect(control, effect) | 订阅控制器内任一选择器滚动过程中的变化事件。 |
| useOnPickerValueChangedEffect(control, effect) | 订阅控制器内所有选择器停止后的变化事件。 |
| withVirtualized(WheelPicker) | 返回使用 Animated.FlatList 虚拟化实现的选择器。 |
| usePickerItemHeight() | 在选择器子树中读取当前 itemHeight。 |
| useScrollContentOffset() | 在选择器子树中读取当前 Animated.Value 滚动偏移。 |
快速验证(运行 Example)
前置条件
| 依赖 | 版本要求 |
| :-- | --- |
| Node.js | >=20 |
| React Native for OpenHarmony | 0.72.139 |
| HarmonyOS SDK | API 21+ |
运行步骤
以下步骤从本仓库源码根目录开始执行。
在仓库根目录生成供示例工程安装的本地安装包:
npm pack --ignore-scripts进入
example目录:cd example安装示例工程依赖:
npm i生成 React Native JavaScript Bundle:
npm run dev使用 DevEco Studio 打开
example/harmony,同步依赖,完成签名配置后构建并运行应用。
约束与限制
兼容性
| 依赖 | 要求 |
| --- | --- |
| React Native for OpenHarmony | 以宿主工程配置为准;示例工程使用 0.72.139 |
| HarmonyOS SDK | 以宿主工程配置为准 |
| Example 工程 compatibleSdkVersion | 6.0.1(21) |
| Example 工程 targetSdkVersion | 6.1.1(24) |
| Node.js | >=18 |
使用限制
- 仅适用于 React Native OpenHarmony 工程。
- 本模块为纯 JavaScript/TypeScript 实现,不包含 C++、ArkTS 或 HAR 原生模块,无需 Autolink,也无需在
oh-package.json5、PackageProvider或 ArkTS 中注册。 WheelPicker是受控组件;value应始终与data中某个数据项的value对应。visibleItemCount必须为大于 0 的奇数,否则在开发环境会抛出错误。DatePicker的date、minDate和maxDate使用YYYY-MM-DD格式。usePickerItemHeight与useScrollContentOffset必须在WheelPicker的自定义渲染树内调用,否则会抛出上下文缺失错误。withPickerControl包装的每个选择器在同一个control内必须使用唯一的pickerName。
系统权限
本库的 HarmonyOS 模块未声明 requestPermissions,不依赖额外的 HarmonyOS 系统权限。
开源 License
本项目采用 MIT License,与上游项目保持一致。
问题反馈渠道
如在使用过程中遇到问题,请在 GitCode 提交Issue,我们会及时跟进。
- 提交问题时建议附上项目版本、RN 版本、OpenHarmony SDK/API 版本、DevEco Studio 版本、设备信息、复现步骤及相关日志。
- 涉及签名、账号、密钥或用户数据时,请勿在 Issue 中上传敏感信息;可按组织安全流程提交脱敏日志。
