blog
blog copied to clipboard
React Native与Iconfont
之前总是想写一些关于学习体会和感受的文章,今天也来一篇关于React Native的教程文章。前段时间我尝试着用React Native构建一个论坛的APP,在这个过程中遇见一个问题: 最开始我是用图片的形式去构建APP中的图标,但用图片构建图标的过程中会遇到一个问题,就是图片的加载速度非常之慢,APP页面加载过程中图标会出现留白的情况,所以我就想要用Iconfont去构建图标。
Iconfont
Iconfont,如字面的意思,就是字体图标。如果你身处在一个视觉或者交互对页面UI一天一变的蛋疼团队,你会深刻的理解使用图片作为图标的不便之处:
- 图标大小会变化,当然你可以通过设置的图片大小去改变图标。但是如果你开始使用的图片的分辨率较低的话,放大图标会造成图标的失真。当然你可以一开始就选择一个高分辨率的图片,但是高分辨的图片会造成加载速度减慢。
- 图标的颜色会变化,假如一开始视觉要求红色的图标,明个脑子一抽风,又要求蓝色的图片。这时候如果你用的是图片,没别的办法,只能换新的图片。
- 图标本身也会变化,今天视觉觉得圆的图标好看,明个觉得方的图标好看,咱又得辛辛苦苦替换图片或者改变图片的应用路径。
有了Iconfont一切就不一样了:
- Iconfont中字体图标都是矢量的,你可以像设置字体大小一样,放大或缩小并且保证不失真。
- Iconfont中字体图标同字体相同,可以通过设置颜色属性改变图标颜色。
- Iconfont字体图标制作简单,并且目前有相当多的线上图标库和制作图标Iconfont的站点。只要上传svg的图标设计稿,就能线上生成iconfont字体文件,而且连使用代码都直接生成。
- Iconfont字体图标具有非常好的兼容性,甚至在IE6中都可以使用。
React Native中使用Iconfont
说了Iconfont这么多的好处,现在我们就尝试着在React Native中使用Iconfont。作为Github的搬运工,想要在React Native中使用Iconfont我们需要使用库:react-native-vector-icons,
react-native-vector-icons
使得React Native支持自定义的图标库,并支持NavBar/TabBar/ToolbarAndroid
等控件与图片形式的图标以及各种样式。其主要优点有:
- 你可以使用自定义的图标库,支持SVG和常规的Iconfont
- 可以在原生的
TabBarIOS
中使用 - 你可以在
Text
组件中像使用emojis表情一样或者在按钮中使用图标 - 如果原生的组件需要的是一个Image(例如:NavigatorIOS),你可以像使用一个
Image
一样使用Icon - 大多数情况下是在JavaScript中使用,因此可以非常灵活的定制样式并且很方便地集成进现有的项目中
- 不需要定义
height
和width
- 可以在样式表中定义类似
size
和color
的属性,而不是通过属性去定义
react-native-vector-icons
内置了很多字体图标,譬如:
-
Entypo
by Daniel Bruce (411 icons) -
EvilIcons
by Alexander Madyankin & Roman Shamin (v1.8.0, 70 icons) -
FontAwesome
by Dave Gandy (v4.7.0, 675 icons) -
Foundation
by ZURB, Inc. (v3.0, 283 icons) -
Ionicons
by Ben Sperry (v3.0.0, 859 icons) -
MaterialIcons
by Google, Inc. (v3.0.1, 932 icons) -
MaterialCommunityIcons
by MaterialDesignIcons.com (v1.9.33, 1932 icons) -
Octicons
by Github, Inc. (v5.0.1, 176 icons) -
Zocial
by Sam Collins (v1.0, 100 icons) -
SimpleLineIcons
by Sabbir & Contributors (v2.4.1, 189 icons)
当然我们希望能够支持我们自定义Iconfont。下面逐步介绍如果在React Native中使用Iconfont。
首先,下载相应的Iconfont文件(*.ttf),我们在阿里巴巴矢量图标库中新建一个项目,将所需要的图标都保存到该项目中,并下载到本地。
我们通过react-native init
的方式初始化一个React Native项目,在其中新建一个assets
目录,其中再建一个font
的文件夹来存储字体文件。我们的项目是在iOS中开发的,首先在iOS进行相应的系统配置。项目目录如下图所示:
iOS配置
react-native-vector-icons
支持相当多的内置字体库,但要使用内置字体库,也需要进行如下的配置,所有的内置字体库文件都在node_modules/react-native-vector-icons
中的Fonts
文件夹下。我们以刚才下载的Iconfont.ttf
为例,我们将其复制进assets/font
文件夹下。然后我们用Xcode
打开ios
目录下*.xcodeproj
项目配置文件。如下图所示:
我们在目录下新建Fonts
文件夹(非必须),并将assets/font
中的Iconfont.ttf
拖拽进工程配置中的Fonts
文件夹,切记!一定要是在Xcode中拖拽进该目录,如果是拖拽进Xcode中时,我们会看见下面的对话框,
我们选择Create groups
并按照需求选择多选项,我们只需要在iOS中使用,就只选择第一项就可以。然后我们打开(项目名)Guides
下的Info.plist
文件。
然后我们在Information property list
下新建Fonts provided by application
属性,并配置Iconfont.ttf
,如下图所示:
Android配置
Android的配置相对比较简单,如果只想使用在react-native-vector-icons
中内置的图标,只需要在项目中android/app/build.gradle
目录下增加:
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
对于自定义的图标库,也只需要在android/app/build.gradle
中添加:
project.ext.vectoricons = [
iconFontNames: ['Iconfont.ttf' ] //添加你需要赋值的字符文件
]
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
使用方法
Icon Component
如果是内置图标库中图标,你可以通过如下方式使用:
import Icon from 'react-native-vector-icons/FontAwesome';
const myIcon = (<Icon name="rocket" size={30} color="#900" />)
对于自定义图标库,我们可以参考一下FontAwesome
是怎么设计的:
/**
* FontAwesome icon set component.
* Usage: <FontAwesome name="icon-name" size={20} color="#4F8EF7" />
*/
import createIconSet from './lib/create-icon-set';
import glyphMap from './glyphmaps/FontAwesome.json';
const iconSet = createIconSet(glyphMap, 'FontAwesome', 'FontAwesome.ttf');
export default iconSet;
export const Button = iconSet.Button;
export const TabBarItem = iconSet.TabBarItem;
export const TabBarItemIOS = iconSet.TabBarItemIOS;
export const ToolbarAndroid = iconSet.ToolbarAndroid;
export const getImageSource = iconSet.getImageSource;
而FontAwesome.json
中代码如下
{
"glass": 61440,
"music": 61441,
"search": 61442,
"envelope-o": 61443,
"heart": 61444,
"star": 61445,
"star-o": 61446,
"user": 61447,
//等等...
}
这样一看使用方法也是非常地简单,综合上述代码,我们首先介绍一下其中的API:
createIconSet(glyphMap, fontFamily[, fontFile])
返回基于glyphMap
的自定义字体集,其中key
是图标的名字,值可以是UTF-8字符,也可以是字符编码(需要注意的是,glyphMap
配置文件中的value
需要是十进制,如果字体库中提供的是十六进制编码,那么就需要将十六进制转换成十进制数)。fontFamily
不是文件名。fontFile
参数是可选的,其目的是支持安卓系统,应该是资源目录下的地址。
那么非常简单,我们也可以编写一个我们自定义的图标组件:
import createIconSet from 'react-native-vector-icons/lib/create-icon-set';
import glyphMap from './Iconfont.json';
const iconSet = createIconSet(glyphMap, 'Iconfont', 'Iconfont.ttf');
export default iconSet;
最后的效果如下:
不仅如此,我们还可以在Icon
中使用Text
组件,
<Icon.Button name="facebook" backgroundColor="#3b5998">
<Text style={{fontFamily: 'Arial', fontSize: 15}}>Login with Facebook</Text>
</Icon.Button>
从而做出如下的效果:
react-native-vector-icons
还有其他的用法,这里只是抛砖迎玉,不再啰嗦,有兴趣大家可以到Github中仔细阅读一下文档。本文章的代码地址如下React-Native-Vector-Icons-Guides,有需要的同学可以参考一下。
请问一下,那个import glyphMap from './Iconfont.json'
中的Iconfont.json
文件怎么生成的?从IconFont下载的并没有这个json文件啊~要自己手动生成?
@Lockie-cn 确实是这样的,Iconfont.json是图标key=>value的关系对应表,其中key值是你自己定义的,只要是唯一的就可以。value对应的是图标库里面的编码,以阿里巴巴适量图标库为例,
其中的十六进制unicode值就是你应该对应的value,但是需要将十六进制转化成十进制。
其实正确添加了iconfont.tff,好像可以很简便的用iconfont。 http://gehaiqing.com/blog/2017/02/22/20170222-react-native-iconfont/
但关键是我现在试用了各种方法各种姿势,依然只能得到一个报错: Unrecognized font family 'iconfont'
我在使用过程中发现一个很不爽的问题, 在iconfont.ttf中添加了新的自定义图标后, 必须react-native run-android 重新生成APK才能显示出来, 这就导致了自定义的图标不能进行热更新,每次都要发新的APK包,这样操作很麻烦, 不知道大神们有没有什么办法解决...
自定义的配置文件是写在 react-native-vector-icons里(和自带的配置文件写在一个文件夹中)呢,还是写在别的地方呢,另外unicode怎么变成10进制呢
MARK
Mark