欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

📌 开发环境声明:本文基于 React Native 0.72.90 版本进行开发适配


🚀 一、开篇引言

选择器(Picker)是移动应用中最基础且重要的交互组件之一,广泛应用于城市选择、日期设置、商品规格选择等场景。@react-native-picker/picker 是 React Native 官方推荐的选择器组件,提供跨平台一致的下拉选择体验。本文将带你深入了解如何在 HarmonyOS 平台上集成和使用这个强大的选择器组件。

1.1 你将学到什么?

  • ✅ @react-native-picker/picker 的核心概念与工作原理
  • ✅ HarmonyOS 平台的完整集成流程
  • ✅ 单列选择器的实现与样式定制
  • ✅ Picker API 的深度解析
  • ✅ 实际应用场景的最佳实践

1.2 适用人群

  • 正在进行 React Native 鸿蒙化迁移的开发者
  • 需要实现选择器功能的应用开发者
  • 对跨平台 UI 组件开发感兴趣的技术爱好者

1.3 为什么选择 @react-native-picker/picker?

特点 说明
官方维护 React Native 社区官方推荐的 Picker 解决方案
跨平台一致 iOS、Android、HarmonyOS 表现一致
简洁易用 API 设计简洁,上手成本低
高度可定制 支持自定义样式、颜色、字体等
类型安全 完整的 TypeScript 类型支持

📦 二、库概览

2.1 基本信息

项目 内容
库名称 @react-native-ohos/picker
原库名称 @react-native-picker/picker
版本信息 2.6.4 (RN 0.72) / 2.11.2 (RN 0.77) / 2.11.4 (RN 0.82)
官方仓库 https://github.com/react-native-picker/picker
鸿蒙仓库 https://gitcode.com/openharmony-sig/rntpc_picker
开源协议 MIT

2.2 版本兼容性

三方库版本 支持RN版本 是否支持Autolink
2.11.4 0.82 No
2.11.2 0.77 No
2.6.4 0.72 Yes
<= 2.6.3@deprecated 0.72 No

2.3 核心能力矩阵

能力项 描述 HarmonyOS 支持
单列选择器 基础下拉选择 ✅ 完全支持
选中值控制 selectedValue 属性 ✅ 完全支持
值变化监听 onValueChange 回调 ✅ 完全支持
禁用状态 enabled 属性 ✅ 完全支持
自定义样式 style 属性 ✅ 完全支持
选中颜色 selectionColor 属性 ✅ 完全支持
选项颜色 Picker.Item color 属性 ❌ 不支持
选项字体 Picker.Item fontFamily ❌ 不支持
多行文本 numberOfLines 属性 ❌ 不支持

2.4 技术架构图

原生平台层

Bridge Layer

React Native 应用层

Picker Component

Native Module

PickerPackage

PickerManager

Android
android.widget.Spinner

iOS
UIPickerView

HarmonyOS
Picker组件

⚡ 三、快速开始

3.1 环境要求

依赖项 版本要求
React Native 0.72.x / 0.77.x
RNOH (鸿蒙框架) 0.72.90 / 0.77.18
HarmonyOS SDK 6.0.0.47+ (API 20)
DevEco Studio 5.0.3+ / 6.0+
Node.js 16.18.0+ / 18.x

3.2 一键安装

创建鸿蒙项目的过程不再进行描述,不懂得看这篇:https://blog.csdn.net/u011178696/article/details/151932277
在这里插入图片描述

npm install @react-native-ohos/picker@2.6.4-rc.1

或使用 yarn:

yarn add @react-native-ohos/picker@2.6.4-rc.1

3.3 验证安装

安装完成后,检查 package.json 文件:

{
  "dependencies": {
    "@react-native-ohos/picker": "^2.6.4-rc.1"
  }
}

🔧 四、HarmonyOS 平台配置

4.1 ManualLink 配置(手动配置)

步骤 1:配置 oh-package.json5(根据自己的版本来)
{
  "overrides": {
    "@rnoh/react-native-openharmony": "0.72.90"
  }
}
步骤 2:引入 HAR 包
"dependencies": {
  "@rnoh/react-native-openharmony": "0.72.90",
  "@react-native-ohos/picker": "file:../../node_modules/@react-native-ohos/picker/harmony/picker.har"
}
步骤 3:配置 CMakeLists.txt
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")

+ add_subdirectory("${OH_MODULES}/@react-native-ohos/picker/src/main/cpp" ./picker)

+ target_link_libraries(rnoh_app PUBLIC rnoh_picker)
步骤 4:配置 PackageProvider.cpp
+ #include "PickerPackage.h"

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
+     std::make_shared<PickerPackage>(ctx)
    };
}
步骤 5:在 ArkTS 侧引入组件

在这里插入图片描述

+ import { RNCPicker, PICKER_TYPE } from "@react-native-ohos/picker"

@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {
+ if (ctx.componentName === PICKER_TYPE) {
+   RNCPicker({
+     ctx: ctx.rnComponentContext,
+     tag: ctx.tag
+   })
+ }
}

const arkTsComponentNames: Array<string> = [
+ PICKER_TYPE
];
步骤 6:引入 RNCPickerPackage
+ import { RNCPickerPackage } from '@react-native-ohos/picker/ts';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
+   new RNCPickerPackage(ctx)
  ];
}

我在适配的时候,有个index.ets中给我导出ets,如下
在这里插入图片描述
不知道什么情况,我手动把.ets删掉了

📱 五、基础使用

5.1 简单选择器

最基础的选择器使用方式:

import { Picker } from '@react-native-ohos/picker';

const [selectedValue, setSelectedValue] = useState('java');

<Picker
  selectedValue={selectedValue}
  onValueChange={(itemValue, itemIndex) => setSelectedValue(itemValue)}
>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="JavaScript" value="js" />
  <Picker.Item label="Python" value="python" />
</Picker>

5.2 禁用状态选择器

const [enabled, setEnabled] = useState(true);

<Picker
  selectedValue={selectedValue}
  onValueChange={(value) => setSelectedValue(value)}
  enabled={enabled}
>
  <Picker.Item label="选项一" value="option1" />
  <Picker.Item label="选项二" value="option2" />
</Picker>

5.3 动态渲染选项

const cities = [
  { label: '北京', value: 'beijing' },
  { label: '上海', value: 'shanghai' },
  { label: '广州', value: 'guangzhou' },
];

<Picker
  selectedValue={selectedCity}
  onValueChange={(value) => setSelectedCity(value)}
>
  {cities.map((city) => (
    <Picker.Item key={city.value} label={city.label} value={city.value} />
  ))}
</Picker>

🎨 六、进阶用法

6.1 联动选择器

当主分类变化时,自动更新子分类选项:

const categories = {
  tech: [
    { label: '人工智能', value: 'ai' },
    { label: '区块链', value: 'blockchain' },
  ],
  entertainment: [
    { label: '电影', value: 'movie' },
    { label: '音乐', value: 'music' },
  ],
};

const [mainCategory, setMainCategory] = useState('tech');
const [subCategory, setSubCategory] = useState('ai');

const handleMainCategoryChange = (value: string) => {
  setMainCategory(value);
  setSubCategory(categories[value][0].value);
};

<Picker
  selectedValue={mainCategory}
  onValueChange={handleMainCategoryChange}
>
  <Picker.Item label="科技" value="tech" />
  <Picker.Item label="娱乐" value="entertainment" />
</Picker>

<Picker
  selectedValue={subCategory}
  onValueChange={setSubCategory}
>
  {categories[mainCategory].map((item) => (
    <Picker.Item key={item.value} label={item.label} value={item.value} />
  ))}
</Picker>

6.2 带图标的选项

const languages = [
  { label: 'Java', value: 'java', icon: '☕' },
  { label: 'JavaScript', value: 'js', icon: '💛' },
  { label: 'Python', value: 'python', icon: '🐍' },
];

<Picker
  selectedValue={selectedLanguage}
  onValueChange={setSelectedLanguage}
>
  {languages.map((lang) => (
    <Picker.Item
      key={lang.value}
      label={`${lang.icon} ${lang.label}`}
      value={lang.value}
    />
  ))}
</Picker>

📚 七、API 详解

7.1 Picker Props

selectedValue

当前选中的值,用于控制选择器的选中状态。

const [value, setValue] = useState('java');

<Picker selectedValue={value} onValueChange={setValue}>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="Python" value="python" />
</Picker>
onValueChange

选中项变化时的回调函数,接收两个参数:itemValueitemIndex

<Picker
  selectedValue={value}
  onValueChange={(itemValue, itemIndex) => {
    console.log('选中值:', itemValue);
    console.log('选中索引:', itemIndex);
    setValue(itemValue);
  }}
>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="Python" value="python" />
</Picker>
style

选择器容器的样式,可设置高度、宽度、颜色等。

<Picker
  selectedValue={value}
  onValueChange={setValue}
  style={{ height: 50, width: 200, backgroundColor: '#f0f0f0' }}
>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="Python" value="python" />
</Picker>
enabled

是否启用选择器,设置为 false 时选择器不可交互。

<Picker
  selectedValue={value}
  onValueChange={setValue}
  enabled={false}
>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="Python" value="python" />
</Picker>
selectionColor

选中指示器的颜色(仅 iOS 和 HarmonyOS 支持)。

<Picker
  selectedValue={value}
  onValueChange={setValue}
  selectionColor="#00d4ff"
>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="Python" value="python" />
</Picker>

7.2 Picker.Item Props

label

选项显示的文本内容。

<Picker.Item label="Java 编程语言" value="java" />
value

选项的值,可以是字符串或数字。

<Picker.Item label="Java" value="java" />
<Picker.Item label="版本号" value={18} />
enabled

是否启用该选项,设置为 false 时选项不可选。

<Picker selectedValue={value} onValueChange={setValue}>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="Python (暂不可用)" value="python" enabled={false} />
</Picker>
color

选项的颜色(HarmonyOS 不支持)。

<Picker.Item label="Java" value="java" color="#ff0000" />

7.3 静态方法

blur

以编程方式关闭选择器(仅 Android 支持)。

const pickerRef = useRef(null);

<Picker ref={pickerRef} selectedValue={value} onValueChange={setValue}>
  <Picker.Item label="Java" value="java" />
</Picker>

<Button title="关闭选择器" onPress={() => pickerRef.current?.blur()} />
focus

以编程方式打开选择器(仅 Android 支持)。

const pickerRef = useRef(null);

<Picker ref={pickerRef} selectedValue={value} onValueChange={setValue}>
  <Picker.Item label="Java" value="java" />
</Picker>

<Button title="打开选择器" onPress={() => pickerRef.current?.focus()} />

⚠️ 八、注意事项与常见问题

8.1 遗留问题

问题 说明
numberOfLines 属性不支持 HarmonyOS 的 Picker 组件不支持多行文本
Picker.Item 的 color 和 fontFamily 不支持 OH 的 Picker 组件不支持单独设置选项样式
themeVariant 属性不支持 主题变体功能暂未适配
itemStyle 不支持设置 textAlign OH 的 Picker 不支持文本对齐设置

8.2 常见问题

Q1: 选择器高度设置不生效?

A: 确保使用 height 属性设置高度,而不是 minHeightmaxHeight

Q2: 如何实现多列选择器?

A: @react-native-picker/picker 是单列选择器,如需多列选择,请使用 @react-native-ohos/react-native-picker

Q3: 选择器样式无法自定义?

A: 部分样式属性在 HarmonyOS 上不支持,请参考核心能力矩阵。


💻 九、完整示例代码

在这里插入图片描述

精美选择器示例

import React, { useState } from 'react';
import {
  View,
  Text,
  StyleSheet,
  ScrollView,
  SafeAreaView,
} from 'react-native';
import { Picker } from '@react-native-ohos/picker';

const languages = [
  { label: 'Java', value: 'java', icon: '☕' },
  { label: 'JavaScript', value: 'js', icon: '💛' },
  { label: 'Python', value: 'python', icon: '🐍' },
  { label: 'TypeScript', value: 'ts', icon: '💙' },
  { label: 'Go', value: 'go', icon: '🐹' },
  { label: 'Rust', value: 'rust', icon: '🦀' },
  { label: 'Swift', value: 'swift', icon: '🍎' },
  { label: 'Kotlin', value: 'kotlin', icon: '🤖' },
];

const themes = [
  { label: '深色模式', value: 'dark' },
  { label: '浅色模式', value: 'light' },
  { label: '跟随系统', value: 'auto' },
];

export default function App() {
  const [selectedLanguage, setSelectedLanguage] = useState('js');
  const [selectedTheme, setSelectedTheme] = useState('light');

  const getLanguageInfo = (value: string) => {
    return languages.find((lang) => lang.value === value);
  };

  return (
    <SafeAreaView style={styles.container}>
      <ScrollView showsVerticalScrollIndicator={false}>
        <View style={styles.header}>
          <Text style={styles.headerTitle}>选择器演示</Text>
          <Text style={styles.headerSubtitle}>@react-native-picker/picker</Text>
        </View>

        <View style={styles.card}>
          <Text style={styles.cardTitle}>当前选择</Text>
          <View style={styles.selectedInfo}>
            <Text style={styles.selectedIcon}>
              {getLanguageInfo(selectedLanguage)?.icon}
            </Text>
            <Text style={styles.selectedName}>
              {getLanguageInfo(selectedLanguage)?.label}
            </Text>
          </View>
          <Text style={styles.selectedValue}>: {selectedLanguage}</Text>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>编程语言选择</Text>
          <View style={styles.pickerWrapper}>
            <Picker
              selectedValue={selectedLanguage}
              onValueChange={(value) => setSelectedLanguage(value)}
              style={styles.picker}
              selectionColor="#00d4ff"
            >
              {languages.map((lang) => (
                <Picker.Item
                  key={lang.value}
                  label={lang.label}
                  value={lang.value}
                />
              ))}
            </Picker>
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>主题设置</Text>
          <View style={styles.pickerWrapper}>
            <Picker
              selectedValue={selectedTheme}
              onValueChange={(value) => setSelectedTheme(value)}
              style={styles.picker}
              selectionColor="#00d4ff"
            >
              {themes.map((theme) => (
                <Picker.Item key={theme.value} label={theme.label} value={theme.value} />
              ))}
            </Picker>
          </View>
        </View>

        <View style={styles.infoCard}>
          <Text style={styles.infoTitle}>组件信息</Text>
          <View style={styles.infoRow}>
            <Text style={styles.infoLabel}>库名称</Text>
            <Text style={styles.infoValue}>@react-native-ohos/picker</Text>
          </View>
          <View style={styles.infoRow}>
            <Text style={styles.infoLabel}>支持平台</Text>
            <Text style={styles.infoValue}>iOS / Android / HarmonyOS</Text>
          </View>
          <View style={styles.infoRow}>
            <Text style={styles.infoLabel}>组件类型</Text>
            <Text style={styles.infoValue}>单列滚动选择器</Text>
          </View>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#1a1a2e',
  },
  header: {
    padding: 24,
    backgroundColor: '#16213e',
    borderBottomLeftRadius: 24,
    borderBottomRightRadius: 24,
  },
  headerTitle: {
    fontSize: 28,
    fontWeight: 'bold',
    color: '#fff',
    textAlign: 'center',
  },
  headerSubtitle: {
    fontSize: 14,
    color: '#888',
    textAlign: 'center',
    marginTop: 5,
  },
  card: {
    margin: 16,
    padding: 24,
    backgroundColor: '#16213e',
    borderRadius: 16,
    alignItems: 'center',
  },
  cardTitle: {
    fontSize: 14,
    color: '#666',
    marginBottom: 12,
  },
  selectedInfo: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 8,
  },
  selectedIcon: {
    fontSize: 36,
    marginRight: 12,
  },
  selectedName: {
    fontSize: 32,
    fontWeight: 'bold',
    color: '#00d4ff',
  },
  selectedValue: {
    fontSize: 14,
    color: '#666',
    marginTop: 8,
  },
  section: {
    margin: 16,
    marginTop: 0,
    backgroundColor: '#16213e',
    borderRadius: 16,
    padding: 16,
  },
  sectionTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#fff',
    marginBottom: 12,
  },
  pickerWrapper: {
    backgroundColor: '#0f0f1a',
    borderRadius: 12,
    borderWidth: 1,
    borderColor: '#333',
    overflow: 'hidden',
  },
  picker: {
    height: 200,
    width: '100%',
    color: '#fff',
  },
  infoCard: {
    margin: 16,
    marginTop: 0,
    backgroundColor: '#16213e',
    borderRadius: 16,
    padding: 16,
    marginBottom: 32,
  },
  infoTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#fff',
    marginBottom: 16,
  },
  infoRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingVertical: 10,
    borderBottomWidth: 1,
    borderBottomColor: '#252540',
  },
  infoLabel: {
    fontSize: 14,
    color: '#888',
  },
  infoValue: {
    fontSize: 14,
    color: '#00d4ff',
    fontWeight: '500',
  },
});

🔗 十、相关资源


📝 十一、总结

本文详细介绍了 @react-native-picker/picker 在 HarmonyOS 平台的使用方法。通过 Picker 组件,你可以轻松实现单列下拉选择功能,支持选中值控制、禁用状态、样式定制等特性。

核心要点

  • ✅ 支持单列下拉选择
  • ✅ 支持选中值控制和变化监听
  • ✅ 支持禁用状态设置
  • ✅ 跨平台一致的 API 设计
  • ✅ 支持 TypeScript 类型

适用场景

  • 语言/主题选择
  • 城市选择
  • 分类筛选
  • 设置选项

希望本文能帮助你在 HarmonyOS 项目中顺利集成选择器组件!

Logo

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

更多推荐