ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-vector-icons — 矢量图标组件

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

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


🚀 一、开篇引言

react-native-vector-icons 是 React Native 生态中最流行、最成熟的矢量图标解决方案,提供了 3000+ 图标,支持 AntDesign、FontAwesome、Ionicons、MaterialIcons、Entypo 等十多种图标集。它通过将 SVG 图标编译为自定义字体文件,实现高性能、可缩放的图标渲染。本文将带你深入了解如何在 HarmonyOS 平台上集成和使用这个强大的图标组件库。

📦 二、库概览

2.1 基本信息

项目 内容
库名称 react-native-vector-icons
版本信息 10.0.3
官方仓库 https://github.com/oblador/react-native-vector-icons
开源协议 MIT

2.2 版本兼容性

三方库版本 支持RN版本 说明
10.0.3 0.72/0.77 已弃用
10.2.0+ 0.72/0.77 推荐使用(新架构)

⚠️ 注意react-native-vector-icons@10.0.3 已被弃用,建议使用新的 per-icon-family 包结构。新版将每个图标集拆分为独立包,

2.3 支持的图标集

图标集 图标数量 说明
AntDesign 800+ 蚂蚁金服设计规范图标
Entypo 411 精美线条图标
EvilIcons 70 简洁图标
Feather 285 简约风格图标
FontAwesome 1600+ 经典图标库
FontAwesome5 1600+ FontAwesome 5 版本
Foundation 283 Foundation 框架图标
Ionicons 1300+ Ionic 框架图标
MaterialIcons 1000+ Material Design 图标
MaterialCommunityIcons 6000+ Material 社区扩展图标
Octicons 200+ GitHub 图标
Zocial 100+ 社交媒体图标
SimpleLineIcons 200+ 简约线条图标

2.4 核心能力矩阵

能力项 描述 HarmonyOS 支持
基础图标渲染 Icon 组件 ✅ 完全支持
自定义颜色 color 属性 ✅ 完全支持
自定义大小 size 属性 ✅ 完全支持
多图标集支持 多种图标库 ✅ 完全支持
自定义图标集 createIconSet ✅ 完全支持
Button 组件 图标按钮 ✅ 完全支持
TabBar 图标 底部导航图标 ✅ 完全支持

2.5 技术架构图

平台层
核心层
图标集
组件层
Icon
Icon.Button
TabBarIcon
createIconSet
AntDesign
FontAwesome
Ionicons
MaterialIcons
MaterialCommunityIcons
字体文件 TTF
字形映射 GlyphMap
iOS
Android
HarmonyOS


📖 三、安装与配置

3.2 安装依赖

在项目根目录执行以下命令:

bash 复制代码
npm install react-native-vector-icons@10.0.3 --legacy-peer-deps

3.3 安装类型声明(TypeScript 项目)

如果使用 TypeScript,需要安装类型声明文件:

bash 复制代码
npm install --save-dev @types/react-native-vector-icons --legacy-peer-deps

⚠️ 注意 :如果遇到 npm 缓存错误,请先执行 npm cache clean --force 清理缓存。

3.4 验证安装

安装完成后,检查 package.json 文件中是否包含以下依赖:

json 复制代码
{
  "dependencies": {
    "react-native-vector-icons": "^10.0.3"
  },
  "devDependencies": {
    "@types/react-native-vector-icons": "^6.4.18"
  }
}

3.5 基本导入

tsx 复制代码
import Icon from 'react-native-vector-icons/AntDesign';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import Ionicons from 'react-native-vector-icons/Ionicons';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';

🔧 四、原生配置

⚠️ 重要提示:react-native-vector-icons 需要配置字体文件才能在 HarmonyOS 平台上正常显示图标。

4.1 复制字体文件

将所需的字体文件复制到 HarmonyOS 项目的资源目录:

步骤一: 创建字体目录

bash 复制代码
mkdir -p harmony/entry/src/main/resources/rawfile/assets/fonts

步骤二: 复制字体文件

node_modules/react-native-vector-icons/Fonts 目录复制需要的字体文件

4.2 注册字体文件

打开 harmony/entry/src/main/ets/pages/Index.ets,注册字体:

typescript 复制代码
import { RNApp } from "@rnoh/react-native-openharmony";

const fonts: Record<string, Resource> = {
    "anticon": $rawfile("assets/fonts/AntDesign.ttf"),
    "AntDesign": $rawfile("assets/fonts/AntDesign.ttf"),
    "FontAwesome": $rawfile("assets/fonts/FontAwesome.ttf"),
    "FontAwesome5-Brand": $rawfile("assets/fonts/FontAwesome5_Brands.ttf"),
    "Ionicons": $rawfile("assets/fonts/Ionicons.ttf"),
    "Material Icons": $rawfile("assets/fonts/MaterialIcons.ttf"),
    "MaterialIcons": $rawfile("assets/fonts/MaterialIcons.ttf"),
    "MaterialCommunityIcons": $rawfile("assets/fonts/MaterialCommunityIcons.ttf"),
    "Entypo": $rawfile("assets/fonts/Entypo.ttf"),
    "Feather": $rawfile("assets/fonts/Feather.ttf"),
    "Foundation": $rawfile("assets/fonts/Foundation.ttf"),
    "Octicons": $rawfile("assets/fonts/Octicons.ttf"),
    "Zocial": $rawfile("assets/fonts/Zocial.ttf"),
    "SimpleLineIcons": $rawfile("assets/fonts/SimpleLineIcons.ttf"),
    "EvilIcons": $rawfile("assets/fonts/EvilIcons.ttf"),
}

@Entry
@Component
struct Index {
    build() {
        Column() {
            RNApp({
                rnInstanceConfig: {
                    fontResourceByFontFamily: fonts
                },
            })
        }
    }
}

⚠️ 注意:字体家族名称需要与字体文件内部定义一致:

  • AntDesign 字体的实际名称是 "anticon"
  • MaterialIcons 字体的实际名称是 "Material Icons"(带空格)
  • 建议同时注册两种名称以确保兼容性

📖 五、API 详解

5.1 Icon 组件

Icon 是最基础的图标组件,用于渲染单个矢量图标。

基本用法:

tsx 复制代码
import Icon from 'react-native-vector-icons/AntDesign';

<Icon name="home" size={24} color="#000" />

5.2 属性详解

name - 图标名称

图标的名称,不同图标集有不同的图标名称。

类型: string

必填:

tsx 复制代码
<Icon name="home" size={24} />
<Icon name="user" size={24} />
<Icon name="setting" size={24} />
size - 图标大小

图标的尺寸,单位为像素。

类型: number

默认值: 12

tsx 复制代码
<Icon name="home" size={16} />
<Icon name="home" size={24} />
<Icon name="home" size={32} />
<Icon name="home" size={48} />
color - 图标颜色

图标的颜色,支持十六进制、RGB、颜色名称等格式。

类型: string

默认值: 'black'

tsx 复制代码
<Icon name="home" color="#007AFF" />
<Icon name="home" color="rgb(255, 0, 0)" />
<Icon name="home" color="red" />
style - 自定义样式

应用于图标的外部样式。

类型: StyleProp<TextStyle>

tsx 复制代码
<Icon 
  name="home" 
  style={{ 
    backgroundColor: '#f0f0f0',
    padding: 10,
    borderRadius: 8
  }} 
/>
allowFontScaling - 字体缩放

是否允许图标跟随系统字体大小缩放。

类型: boolean

默认值: true

tsx 复制代码
<Icon name="home" allowFontScaling={false} />

5.3 Icon.Button 组件

Icon.Button 是带有图标的按钮组件,常用于工具栏、列表项等场景。

基本用法:

tsx 复制代码
import Icon from 'react-native-vector-icons/Ionicons';

<Icon.Button 
  name="facebook" 
  backgroundColor="#3b5998" 
  onPress={() => console.log('Facebook')}
>
  Login with Facebook
</Icon.Button>
Button 特有属性
属性 类型 说明
backgroundColor string 按钮背景颜色
borderRadius number 圆角大小
onPress function 点击回调
disabled boolean 是否禁用
underlayColor string 点击时的背景颜色
iconStyle object 图标样式
buttonStyle object 按钮样式
textStyle object 文本样式
tsx 复制代码
<Icon.Button
  name="logo-google"
  backgroundColor="#DB4437"
  borderRadius={8}
  iconStyle={{ marginRight: 10 }}
  onPress={handleGoogleLogin}
>
  Sign in with Google
</Icon.Button>

5.4 createIconSet 自定义图标集

createIconSet 允许创建自定义图标集,支持使用自定义字体文件。

基本用法:

tsx 复制代码
import { createIconSet } from 'react-native-vector-icons';

const glyphMap = {
  'custom-icon-1': 0xe800,
  'custom-icon-2': 0xe801,
  'custom-icon-3': 0xe802,
};

const CustomIcon = createIconSet(glyphMap, 'CustomFont', 'CustomFont.ttf');

<CustomIcon name="custom-icon-1" size={24} color="#000" />

参数说明:

参数 类型 说明
glyphMap object 图标名称与 Unicode 的映射
fontFamily string 字体名称
fontFile string 字体文件名(Android)

5.5 getImageSource 获取图片源

将图标转换为图片源,可用于 Image 组件或导航栏图标。

基本用法:

tsx 复制代码
import Icon from 'react-native-vector-icons/Ionicons';

const source = Icon.getImageSource('home', 24, '#000');

<Image source={source} />

用于导航栏:

tsx 复制代码
import Icon from 'react-native-vector-icons/Ionicons';

const homeIcon = await Icon.getImageSource('home', 24, '#007AFF');

navigation.setOptions({
  headerRight: () => (
    <Image source={homeIcon} />
  ),
});

💡 六、使用示例

ts 复制代码
import React from 'react';
import { View, Text, StyleSheet, SafeAreaView, ScrollView, Alert, TouchableOpacity } from 'react-native';
import AntDesign from 'react-native-vector-icons/AntDesign';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import Ionicons from 'react-native-vector-icons/Ionicons';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';

interface IconItemProps {
  icon: React.ReactNode;
  name: string;
}

const IconItem: React.FC<IconItemProps> = ({ icon, name }) => (
  <View style={styles.iconItem}>
    {icon}
    <Text style={styles.iconName}>{name}</Text>
  </View>
);

const VectorIconsDemo: React.FC = () => {
  const handlePress = (name: string) => {
    Alert.alert('图标点击', `你点击了 ${name} 图标`);
  };

  return (
    <SafeAreaView style={styles.container}>
      <ScrollView contentContainerStyle={styles.content}>
        <Text style={styles.title}>矢量图标示例</Text>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>AntDesign 图标集</Text>
          <View style={styles.row}>
            <TouchableOpacity onPress={() => handlePress('home')}>
              <IconItem icon={<AntDesign name="home" size={32} color="#007AFF" />} name="home" />
            </TouchableOpacity>
            <TouchableOpacity onPress={() => handlePress('user')}>
              <IconItem icon={<AntDesign name="user" size={32} color="#4ECDC4" />} name="user" />
            </TouchableOpacity>
            <TouchableOpacity onPress={() => handlePress('setting')}>
              <IconItem icon={<AntDesign name="setting" size={32} color="#FF6B6B" />} name="setting" />
            </TouchableOpacity>
            <TouchableOpacity onPress={() => handlePress('heart')}>
              <IconItem icon={<AntDesign name="heart" size={32} color="#E74C3C" />} name="heart" />
            </TouchableOpacity>
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>Ionicons 图标集</Text>
          <View style={styles.row}>
            <IconItem icon={<Ionicons name="home-outline" size={32} color="#FF9500" />} name="home-outline" />
            <IconItem icon={<Ionicons name="person-outline" size={32} color="#00C7BE" />} name="person-outline" />
            <IconItem icon={<Ionicons name="settings-outline" size={32} color="#5856D6" />} name="settings-outline" />
            <IconItem icon={<Ionicons name="heart-outline" size={32} color="#FF2D55" />} name="heart-outline" />
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>MaterialIcons 图标集</Text>
          <View style={styles.row}>
            <IconItem icon={<MaterialIcons name="home" size={32} color="#607D8B" />} name="home" />
            <IconItem icon={<MaterialIcons name="person" size={32} color="#795548" />} name="person" />
            <IconItem icon={<MaterialIcons name="settings" size={32} color="#9C27B0" />} name="settings" />
            <IconItem icon={<MaterialIcons name="favorite" size={32} color="#F44336" />} name="favorite" />
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>图标按钮 (Icon.Button)</Text>
          <FontAwesome.Button
            name="facebook"
            backgroundColor="#3b5998"
            borderRadius={8}
            style={styles.socialButton}
            onPress={() => Alert.alert('Facebook', 'Facebook 登录')}
          >
            <Text style={styles.buttonText}>使用 Facebook 登录</Text>
          </FontAwesome.Button>
          <FontAwesome.Button
            name="google"
            backgroundColor="#DB4437"
            borderRadius={8}
            style={styles.socialButton}
            onPress={() => Alert.alert('Google', 'Google 登录')}
          >
            <Text style={styles.buttonText}>使用 Google 登录</Text>
          </FontAwesome.Button>
          <Ionicons.Button
            name="logo-apple"
            backgroundColor="#000000"
            borderRadius={8}
            style={styles.socialButton}
            onPress={() => Alert.alert('Apple', 'Apple 登录')}
          >
            <Text style={styles.buttonText}>使用 Apple 登录</Text>
          </Ionicons.Button>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>不同尺寸</Text>
          <View style={styles.row}>
            <IconItem icon={<MaterialCommunityIcons name="heart" size={16} color="#E91E63" />} name="16px" />
            <IconItem icon={<MaterialCommunityIcons name="heart" size={24} color="#E91E63" />} name="24px" />
            <IconItem icon={<MaterialCommunityIcons name="heart" size={32} color="#E91E63" />} name="32px" />
            <IconItem icon={<MaterialCommunityIcons name="heart" size={48} color="#E91E63" />} name="48px" />
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>不同颜色</Text>
          <View style={styles.row}>
            <IconItem icon={<MaterialCommunityIcons name="star" size={32} color="#007AFF" />} name="蓝色" />
            <IconItem icon={<MaterialCommunityIcons name="star" size={32} color="#34C759" />} name="绿色" />
            <IconItem icon={<MaterialCommunityIcons name="star" size={32} color="#FF9500" />} name="橙色" />
            <IconItem icon={<MaterialCommunityIcons name="star" size={32} color="#FF3B30" />} name="红色" />
          </View>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  content: {
    padding: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    textAlign: 'center',
    color: '#333',
  },
  section: {
    marginBottom: 24,
  },
  sectionTitle: {
    fontSize: 16,
    fontWeight: '600',
    marginBottom: 12,
    color: '#333',
  },
  row: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'flex-start',
  },
  iconItem: {
    width: 80,
    alignItems: 'center',
    backgroundColor: '#fff',
    padding: 12,
    borderRadius: 8,
    marginRight: 8,
    marginBottom: 8,
  },
  iconName: {
    fontSize: 11,
    color: '#666',
    marginTop: 6,
    textAlign: 'center',
  },
  socialButton: {
    marginBottom: 12,
    paddingVertical: 10,
  },
  buttonText: {
    color: '#fff',
    fontSize: 15,
    fontWeight: '500',
  },
});

export default VectorIconsDemo;

❓ 七、常见问题

7.1 图标显示为方框或乱码

问题描述: 图标显示为方框 □ 或乱码。

解决方案:

  1. 确认字体文件已正确复制到 rawfile/assets/fonts 目录
  2. 确认字体已在 Index.ets 中正确注册
  3. 确认字体名称与图标集匹配
typescript 复制代码
const fonts: Record<string, Resource> = {
    "AntDesign": $rawfile("assets/fonts/AntDesign.ttf"),
};

7.2 如何查找图标名称?

解决方案:

  1. 访问 React Native Vector Icons 目录
  2. 在页面中选择图标集,搜索图标
  3. 复制图标名称使用

7.3 如何使用自定义图标?

解决方案:

使用 createIconSet 创建自定义图标集:

tsx 复制代码
import { createIconSet } from 'react-native-vector-icons';

const glyphMap = {
  'my-icon': 0xe001,
};

const MyIcon = createIconSet(glyphMap, 'MyIconFont', 'MyIconFont.ttf');

7.4 HarmonyOS 特殊配置

注意事项:

在 HarmonyOS 平台上使用图标时,建议添加以下样式以获得更好的显示效果:

tsx 复制代码
<Icon
  name="home"
  size={24}
  color="#007AFF"
  style={{
    includeFontPadding: false,
    textAlignVertical: 'center'
  }}
/>

📋 八、属性参考

Icon 组件属性

属性 类型 必填 默认值 说明
name string - 图标名称
size number 12 图标大小
color string 'black' 图标颜色
style StyleProp <TextStyle> - 自定义样式
allowFontScaling boolean true 是否跟随系统缩放

Icon.Button 组件属性

属性 类型 必填 默认值 说明
name string - 图标名称
size number 12 图标大小
color string 'white' 图标颜色
backgroundColor string '#007AFF' 按钮背景颜色
borderRadius number 0 圆角大小
onPress function - 点击回调
disabled boolean false 是否禁用
iconStyle object - 图标样式
buttonStyle object - 按钮样式
textStyle object - 文本样式

📝 九、总结

react-native-vector-icons 为 HarmonyOS 平台提供了丰富的矢量图标解决方案,通过配置字体文件即可使用 3000+ 图标。通过本篇文章,你已经掌握了:

  • 字体文件的配置方法
  • 多种图标集的使用
  • Icon 和 Icon.Button 组件的 API
  • TabBar 图标的实现
  • 自定义图标集的创建

开源协议

本项目基于 The MIT License (MIT) ,请自由地享受和参与开源。

相关推荐
弓.长.2 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-indicators — 加载指示器组件
react native·react.js·harmonyos
autumn200512 小时前
Flutter 框架跨平台鸿蒙开发 - 虚拟纪念馆
flutter·华为·harmonyos
2301_8227032012 小时前
渐变壁纸生成:基于鸿蒙Flutter的跨平台壁纸创建工具
flutter·华为·harmonyos·鸿蒙
人间打气筒(Ada)13 小时前
「码动四季·开源同行」HarmonyOS应用开发:常见组件
华为·开源·harmonyos·组件·布局·鸿蒙开发
三声三视13 小时前
ArkTS 自定义组件完全指南:@Builder、@Extend、@Styles 实战解析
华为·harmonyos
软件工程师文艺15 小时前
从0到1:Claude Code如何用React构建CLI应用
前端·react.js·前端框架
Utopia^15 小时前
Flutter 框架跨平台鸿蒙开发 - 旅行预算管家
flutter·华为·harmonyos
M ? A16 小时前
Vue 迁移 React 实战:VuReact 一键自动化转换方案
前端·vue.js·经验分享·react.js·开源·自动化·vureact
李李李勃谦16 小时前
Flutter 框架跨平台鸿蒙开发 - 星空识别助手
flutter·华为·harmonyos