2018的第一个月份,希望能多记录一些实用的东西吧,今天来分享一下Android中的矢量图(SVG)的用法,我首先会说一下矢量图的基本使用方法,然后说一下阿里巴巴矢量图标库Iconfont的使用,最后会通过一个开源库的学习来自定义自己的矢量图标库,你可以把它集成到自己的项目框架中去,方便以后自己在自己的项目中扩展,这在搭建基础项目框架中都是能用到的,也可以丰富自己的技术栈的整合。好了,废话不多说了,说干就干吧!
一、在Android中使用SVG矢量图
理论知识说明:Google在Android 5.X中提供了两个新API来帮助支持SVG: 1、 VectorDrawable(显示SVG图标) 2、AnimatedVectorDrawable(SVG动画)
1、什么是SVG?
SVG (Scalable Vector Graphics, 可伸缩矢量图形) 是W3C 推出的一种开放标准的文本式矢量图形描述语言,他是基于XML的、专门为网络而设计的图像格式,SVG是一种采用XML来描述二维图形的语言,所以它可以直接打开xml文件来修改和编辑。
2、矢量图有哪些优点?
3、Path的介绍:
M = moveto(M X,Y) :将画笔移动到指定的坐标位置
L = lineto(L X,Y) :画直线到指定的坐标位置
H = horizontal lineto(H X):画水平线到指定的X坐标位置
V = vertical lineto(V Y):画垂直线到指定的Y坐标位置
C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次贝赛曲线
S = smooth curveto(S X2,Y2,ENDX,ENDY):三次贝赛曲线
Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二次贝赛曲线
T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射前面路径后的终点
A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧线
Z = closepath():关闭路径
说明一点,我的数学知识菜的不想多提,所以这些东西我是真不懂,大家有兴趣的可以自己去研究一下,牛逼的人你想画什么就能画什么。
4、具体使用步骤:
1、我这里新建一个工程SVGDemo,然后我们在drawable文件夹下右键新建Vector Asset文件,如图所示:
2、然后会弹出一个对话框,这里可以创建我们的svg图标,默认选中的类型是Google的Material类型,图标是安卓机器人,我们可以点击Icon图标选择自己想要的,如果你本地有你需要使用的矢量图,你可以选择Local file类型,选择制作你自己想要的矢量图,如图所示:
3、创建完成后,我们可以发现drawable目录下生成了一个新的xml文件,这个就是我们的矢量图文件,可以看到是通过path去定义路径,然后内部使用上面介绍的api进行路径的描绘来实现的矢量图标,我这里选择了一个返回按钮,如图所示:
这里需要说明的是,Android官方虽然给我们提供了很多矢量图标,但是在实际开发中我们一般都不会去使用的,因为它太丑了!那我们该如何获取矢量图呢?很简单,你可以直接找你们公司的UI妹子让她给你提供,或者你又不想撩妹的,你可以去阿里巴巴矢量图标库中下载,里面有各种各样好看的图标,基本能满足你的日常需求,这里随便截取了一张图给大家看一下,三种类型的图标随你选择:
4、创建完成之后,我们来看如何使用?基本使用方式:我在MainActivity的布局文件中放置了一个TextView,然后把这个图标引入进去,如图所示:
可以看到,通过上面这几个步骤,我们就可以使用我们的矢量图了,那看到这里不知道大家有没有发现一个问题呢?如果我想再添加一个这样的返回按钮并且不是绿色的我想要红色的,那这个时候怎么办呢?有人会说了:再复制出一个xml文件,把颜色改成红色的不就好了。对,这位大哥,你说的对,你开心就好,那照这个逻辑,我想要一个全系列颜色的,我得复制多少个文件啊,显而易见太麻烦了,此种方式不可取,那我们该怎么办呢?其实解决的方式很简单,我们需要把这些图标制作成字体,合成在一个字体文件里面,然后调用字体里面的一些字符串进行显示就行了。
二、在Android中使用Iconfont图标
(一)理论基础——使用步骤总结:
1: 从iconfont平台选择要使用到的图标,并下载至本地;复制字体文件到项目 assets 目录;
2: 打开下载下来的文件,并在目录中打开demo.html,找到图标相对应的 HTML 实体字符码
3: 打开 res/values/strings.xml,添加 string 值;
4:打开 activity_main.xml,添加 string 值到 TextView:
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/icons" />
5:为 TextView 指定文字:
import android.graphics.Typeface;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Typeface iconfont = Typeface.createFromAsset(getAssets(), "iconfont/iconfont.ttf");
TextView textview = (TextView)findViewById(R.id.like);
textview.setTypeface(iconfont);
}
(二)具体操作步骤:
1、这一步就是下载文件,我这里使用一张动态图来进行说明:
然后我们打开下载的文件,将iconfont.ttf文件复制到assets目录下。
2、打开下载文件中的demo_unicode.html文件,然后将需要使用的图标的unicode编码放到values的strings文件中,我这里选择了购物车和删除图标,如下所示:
3、然后我们在xml文件中新增一个TextView控件,文本内容引用购物车这个文本,代码如下:
4、在Activity中绑定控件,使用Typeface类设置文本,代码如下:
TextView textView = (TextView) findViewById(R.id.tv_cart);
Typeface typeface = Typeface.createFromAsset(getAssets(),"iconfont.ttf");
textView.setTypeface(typeface);
5、最后运行的效果图如下,可以看到购物车图标完美的被加载出来了:
三、使用Iconfont制作自己的字体图标库
需要说明的是,这里是基于GitHub上的一个开源库进行设计的,我们需要在项目中引入它的核心模块,它所提供的字体模块你可以不引用,因为这里是制作自己的字体库。
项目地址:https://github.com/mikepenz/Android-Iconics
大家可以先去大体浏览一些这个库的内容,然后再接着往下看如何自定义字体图标库。
1、首先在我们本地的项目中添加核心依赖:
compile "com.mikepenz:iconics-core:2.8.1@aar"
2、新建一个类MyIconFont,实现这个库中的ITypeface接口,或者你可以直接copy这个库中的CustomFont类然后进行修改,CustomFont类在app包下,大家可以点击去看看,我这里还继续上一小节中的下载的字体进行制作,如下所示:
首先来看图标库中的代码,代码中都添加了注释,也比较简单:
package com.jarchie.svg;
import android.content.Context;
import android.graphics.Typeface;
import com.mikepenz.iconics.typeface.IIcon;
import com.mikepenz.iconics.typeface.ITypeface;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
/**
* Created by Jarchie on 2018\1\12.
* 自定义字体图标库
*/
@SuppressWarnings("WeakerAccess")
public class MyIconFont implements ITypeface{
private static final String TTF_FILE = "iconfont.ttf"; //字体名称
private static Typeface typeface = null;
private static HashMap mChars;
@Override
public IIcon getIcon(String key) { //通过key拿到内部类中的Icon
return Icon.valueOf(key);
}
@Override
public HashMap getCharacters() { //将字符串存到HashMap中
if (mChars == null) {
HashMap aChars = new HashMap<>();
for (Icon v : Icon.values()) {
aChars.put(v.name(), v.character); //字符串的名字和值put进去,一一对应
}
mChars = aChars;
}
return mChars;
}
@Override
public String getMappingPrefix() { //这个是Icon类中你自己定义的字体的前缀,一定不能搞错,否则找不到对应的字体
return "archie";
}
@Override
public String getFontName() { //字体名字,可以随便写
return "JarchieFont";
}
@Override
public String getVersion() { //版本号
return "1.0.0";
}
@Override
public int getIconCount() { //字体数量
return mChars.size();
}
@Override
public Collection getIcons() { //返回一个有序集合
Collection icons = new LinkedList<>();
for (Icon value : Icon.values()) {
icons.add(value.name());
}
return icons;
}
@Override
public String getAuthor() { //作者
return "Jarchie";
}
@Override
public String getUrl() { //域名URL,可以随便写,也可不写
return "https://github.com/JArchie/SVGDemo";
}
@Override
public String getDescription() { //描述内容
return "The custom icon font for Iconics";
}
@Override
public String getLicense() { //授权
return "XXX Licensed";
}
@Override
public String getLicenseUrl() { //授权地址
return "https://github.com/JArchie/SVGDemo";
}
@Override
public Typeface getTypeface(Context context) { //获取Typeface对象
if (typeface == null) {
try {
typeface = Typeface.createFromAsset(context.getAssets(), TTF_FILE);
} catch (Exception e) {
return null;
}
}
return typeface;
}
@SuppressWarnings({"WeakerAccess", "unused"})
public enum Icon implements IIcon {
archie_all('\ue696'),
archie_back('\ue697'),
archie_cart('\ue698'),
archie_category('\ue699'),
archie_close('\ue69a'),
archie_comments('\ue69b'),
archie_cry('\ue69c'),
archie_delete('\ue69d'),
archie_edit('\ue69e'),
archie_form('\ue6a2'),
archie_qrcoed('\ue6a9'),
archie_search('\ue6ac'),
archie_selected('\ue6ad'),
archie_set('\ue6ae'),
archie_success('\ue6b1');
char character;
Icon(char character) {
this.character = character;
}
public String getFormattedName() {
return "{" + name() + "}";
}
public char getCharacter() {
return character;
}
public String getName() {
return name();
}
// remember the typeface so we can use it later
private static ITypeface typeface;
public ITypeface getTypeface() {
if (typeface == null) {
typeface = new MyIconFont();
}
return typeface;
}
}
}
这里需要注意的是,在代码中转换unicode字符的时候,需要将“”替换为“\u”。
3、自定义我们的Application,这在开源库中有说明,具体代码为:
package com.jarchie.svg;
import android.app.Application;
import com.mikepenz.iconics.Iconics;
/**
* Created by Jarchie on 2018\1\12.
* 自定义Application
*/
public class BaseApp extends Application {
@Override
public void onCreate() {
super.onCreate();
//only required if you add a custom or generic font on your own
Iconics.init(this);
//register custom fonts like this (or also provide a font definition file)
Iconics.registerFont(new MyIconFont());
}
}
4、具体使用,测试是否正常显示:
这里我在xml文件中新增了一个ImageView和一个TextView,然后通过使用我们自己的字体图标库来为它们设置内容,代码如下:
ImageView imageView = (ImageView) findViewById(R.id.iv_set);
TextView textView1 = (TextView) findViewById(R.id.tv_qrcode);
imageView.setImageDrawable(new IconicsDrawable(this).icon(MyIconFont.Icon.archie_set)
.color(Color.BLUE).sizeDp(50));
textView1.setBackground(new IconicsDrawable(this).icon(MyIconFont.Icon.archie_qrcoed).sizeDp(50));
5、最后实现的效果为:
四、遇到的问题
自定义的图标库无法在xml中引用,使其显示,不知道是因为研究的不够还是这个库本身的BUG,在后续的学习中我会继续跟进这个问题。
案例源码地址:https://github.com/JArchie/SVGDemo
好了,本篇要分享的东西就是这么多,欢迎大家留言探讨,多多批评指正!