在 React Native 中使用 Evil Icons:@react-native-vector-icons/evil-icons 字体包完整指南
【免费下载链接】react-native-vector-iconsCustomizable Icons for React Native with support for image source and full styling.项目地址: https://gitcode.com/gh_mirrors/re/react-native-vector-icons
Evil Icons 是一套线条风格(stroke-based)的图标字体,本文以仓库中的 packages/evil-icons/README.md 为主线,系统讲解@react-native-vector-icons/evil-icons的安装、动态/静态两种导入方式、Expo 配置插件接入,并结合仓库源码(createIconSet实现、glyphmap、Android 原生包)深入说明其底层工作原理。读完本文,你将能够在 React Native 与 Expo 项目中正确、高效地集成 Evil Icons,并理解两种字体加载策略的取舍。
一、Evil Icons 字体包是什么
Evil Icons 是 react-native-vector-icons 生态中面向 Evil Icons 字体(上游版本 1.10.1)的独立包。与直接依赖整个 react-native-vector-icons 不同,当前仓库采用"每个图标集一个独立 npm 包"的 monorepo 结构,@react-native-vector-icons/evil-icons即对应 packages/evil-icons 目录,包内包含:
fonts/EvilIcons.ttf:字体文件本体;glyphmaps/EvilIcons.json:图标名到 Unicode 码点的映射表(共 72 个图标);src/index.ts/src/static.ts:动态加载与静态加载两种入口;app.plugin.js:Expo 配置插件;android/:用于 autolinking 注册的原生包。
从 package.json 可以看到,该包要求node >= 18.0.0,peerDependencies 为react、react-native,以及可选的@expo/config-plugins(>= 10.0.0,仅在使用 Expo 配置插件时需要)。当前仓库中该包版本为 13.1.2。
二、安装
在 React Native 或 Expo 项目中执行:
npm install @react-native-vector-icons/evil-icons包内exports字段(见 package.json)暴露了以下子路径,均可直接引用:
| 子路径 | 用途 |
|---|---|
@react-native-vector-icons/evil-icons | 默认入口(动态加载字体) |
@react-native-vector-icons/evil-icons/static | 静态入口(配合原生构建) |
@react-native-vector-icons/evil-icons/glyphmaps/*.json | 图标映射表 JSON |
@react-native-vector-icons/evil-icons/fonts/*.ttf | 字体文件 |
@react-native-vector-icons/evil-icons/app.plugin.js | Expo 配置插件 |
三、基础用法
最简单的用法是从默认入口导入组件并渲染:
import { EvilIcons } from '@react-native-vector-icons/evil-icons'; // ... <EvilIcons name="house" color="#ff0000" size={20} />该 README 还给出了两种入口的取舍建议:
// 静态导入(推荐用于开发构建,避免字体被打包两次) import { EvilIcons } from '@react-native-vector-icons/evil-icons/static'; // 或使用动态字体加载(默认入口,参见 Expo 配置指南) import { EvilIcons } from '@react-native-vector-icons/evil-icons';组件的核心 props 与 react-native-vector-icons 保持一致:name(图标名)、color(颜色,可传任何TextStyle['color'])、size(字号)。此外还支持style、children、allowFontScaling(默认false)与innerRef等属性,完整定义见 packages/common/src/create-icon-set.tsx 中的IconProps。
3.1 图标命名与 glyphmap
name的可选值来自 glyphmaps/EvilIcons.json,共 72 个图标,例如:archive、arrow-down、arrow-left、arrow-right、arrow-up、bell、calendar、camera、cart、chart、check、chevron-down、chevron-left、chevron-right、chevron-up、clock、close、close-o、comment、credit-card、envelope、exclamation、external-link、eye、gear、heart、image、like、link、location、lock、minus、navicon、paperclip、pencil、play、plus、pointer、question、redo、refresh、retweet、sc-facebook、sc-github、sc-google-plus、sc-instagram、sc-linkedin、sc-odnoklassniki、sc-pinterest、sc-skype、sc-soundcloud、sc-telegram、sc-tumblr、sc-twitter、sc-vimeo、sc-vk、sc-youtube、search、share-apple、share-google、spinner、spinner-2、spinner-3、star、tag、trash、trophy、undo、unlock、user、house。
映射表中每个图标名对应一个十进制的 Unicode 码点(如"house": 61696,即 U+F100)。在渲染时,createIconSet内部通过resolveGlyph将码点转换为字符(String.fromCodePoint(glyph)),未知名称则回退为'?',实现见 packages/common/src/create-icon-set.tsx。
3.2 TypeScript 类型支持
两个入口文件都会导出图标名联合类型:
export type EvilIconsIconName = keyof typeof glyphMap;见 src/index.ts 与 src/static.ts。这意味着nameprop 会获得完整的类型提示与编译期校验,拼写错误的图标名会在编译阶段被拦截。
四、默认入口(动态加载)与静态入口(/static)如何选择
这是本 README 引出的核心话题,完整决策背景见 docs/SETUP-EXPO.md:
- 默认入口(动态加载):
src/index.ts中createIconSet的配置带有fontSource: require('../fonts/EvilIcons.ttf')(见 src/index.ts),Metro 会把.ttf作为 JS 资源打进 bundle。图标首次渲染时,运行时通过expo-font(底层是@react-native-vector-icons/common的dynamicLoader)将字体注册到原生文本系统,无需任何原生配置。这是唯一能在 Expo Go 中工作的方式,且字体可以随 OTA 更新。前提是 Expo SDK >= 52。 - 静态入口(/static):
src/static.ts不携带fontSource(见 src/static.ts),Metro 不会打包.ttf。字体由 autolinking 在构建期通过每个包的build.gradle/.podspec拷贝进原生二进制,再由 Expo 配置插件把它注册进 iOS 的Info.plist(UIAppFonts)。该方式只适用于 Development Build,不适用于 Expo Go,且内嵌字体无法通过 OTA 更换。
[!NOTE] 如果只使用默认入口、但又在开发构建中启用了 autolinking,同一个
.ttf会同时以 JS 资源与原生资源两种方式进入包体,造成体积翻倍;此时要么改用/static,要么在 autolinking 中排除该包,只保留 JS 侧副本。
关于动态加载,@react-native-vector-icons/common还导出了控制函数:isDynamicLoadingEnabled()、isDynamicLoadingSupported()、setDynamicLoadingEnabled()与setDynamicLoadingErrorCallback(),可用于检测/开关动态加载能力或在 OTA 更新缺失字体时捕获错误。
五、Expo Config Plugin 配置
如果你使用静态导入(/static)并在 Expo 开发构建中运行,需要在app.json或app.config.js的plugins数组中注册本包的配置插件:
{ "expo": { "plugins": ["@react-native-vector-icons/evil-icons"] } }配置完成后执行npx expo prebuild重新生成原生工程。
插件实现见 app.plugin.js:它基于@expo/config-plugins的withInfoPlist,把EvilIcons.ttf追加到UIAppFonts数组(c.modResults.UIAppFonts),从而让 iOS 在应用启动时加载该字体。注意本插件只负责 iOS 侧注册,Android 侧由 autolinking 直接处理字体拷贝。
[!WARNING] 不要重复配置:不要再把
node_modules/@react-native-vector-icons/evil-icons/fonts/EvilIcons.ttf手动加入expo-font的 config plugin 配置,否则会造成字体配置重复。
六、底层实现:createIconSet 如何工作
两个入口都基于@react-native-vector-icons/common的createIconSet工厂函数构建(packages/common/src/create-icon-set.tsx)。其核心逻辑包括:
- 字体引用解析:根据平台生成
fontFamily引用——Windows 为/Assets/{fontFileName}#{postScriptName},Android 为字体文件名去扩展名,其余平台使用postScriptName(见fontReference的Platform.select,create-icon-set.tsx)。 - 样式覆盖:强制
fontFamily: fontReference、fontWeight: 'normal'、fontStyle: 'normal',防止父级文本样式破坏图标字形。 - 动态字体加载:当存在
fontSource且动态加载开启时,首次渲染通过dynamicLoader.loadFontAsync异步加载字体,加载完成前渲染空字符以避免"豆腐块"(create-icon-set.tsx)。 - 图像源 API:组件命名空间上还挂载了
getImageSource(异步)与getImageSourceSync(同步)两个静态方法,可把图标转为图片源对象,用于Image组件、TabBarIcon等场景,内部走create-icon-source-cache缓存。
也就是说,<EvilIcons name="house" size={20} color="#ff0000" />最终渲染为一个设置了对应fontFamily与字形字符的<Text>节点。
七、Android 侧原生注册
android/目录下提供了用于 autolinking 的原生包:VectorIconsEvilIconsPackage.kt。它继承BaseReactPackage,但getModule返回null、getReactModuleInfoProvider返回空映射——从源码结构看,这是一个"占位"包,主要作用是让 autolinking 发现并保留该包的原生构建产物(字体拷贝配置),本身不注册任何原生模块。因此,在纯 JS 渲染场景(如默认动态加载)下,即使不依赖该原生包也能正常工作;静态加载场景则依赖 autolinking 在构建期完成字体拷贝。
八、版本对应关系
README 明确说明:在 12.0.0 版本之前,字体包的版本号直接跟随上游 Evil Icons 版本;12.0.0 之后改为跟随 react-native-vector-icons(RNVI)版本体系。当前对应关系如下:
| RNVI 版本 | 上游 Evil Icons 版本 |
|---|---|
| > 12.0.0 | 1.10.1 |
仓库中 package.json 的 devDependencies 锁定evil-icons: 1.10.1,与表格一致;字体生成流程由根目录 scripts/generate-fonts.sh 与字体包生成器(packages/generator-react-native-vector-icons)协作完成,相关演进记录可查看 packages/evil-icons/CHANGELOG.md(如 12.0.0 起"字体包负责字体拷贝"、12.3.0 起导出字体文件与 glyphmaps、13.1.0 起加入 Expo 配置插件)。
九、更多平台与后续参考
- 不使用 Expo 的纯 React Native 工程,请参考 docs/SETUP-REACT-NATIVE.md;
- Web 端集成方式见 docs/SETUP-WEB.md;
- 自定义字体(含 FontAwesome Pro 等 Pro 字体)需通过
createIconSet配合fontSource实现,详见 README.md; - 仓库的整体架构与全部字体包列表见根目录 README.md;
- 参与开发请遵循 CONTRIBUTING.md 中的工作流。
十、总结
@react-native-vector-icons/evil-icons是一个高度工程化的字体包:默认入口借助动态字体加载做到"开箱即用、Expo Go 可用、支持 OTA";静态入口配合 Expo 配置插件与 autolinking 做到"原生打包、无 JS 资源冗余"。理解createIconSet的字体引用解析与resolveGlyph字形映射机制,能帮助你在渲染异常、字体重复打包等场景下快速定位根因,并根据 Expo/纯 RN、Expo Go/Development Build 的不同组合选择正确的导入方式。
【免费下载链接】react-native-vector-iconsCustomizable Icons for React Native with support for image source and full styling.项目地址: https://gitcode.com/gh_mirrors/re/react-native-vector-icons
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考