Android中使用Iconfont图标制作自己的矢量图库

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、矢量图有哪些优点?

  • 矢量图是用点和线来描述图形,所以文件会比较小,同时也能提供高清晰的画面 
  • 矢量图缩放自由且不会失真,完全适配于任何分辨率的屏幕 
  • 矢量图的是以xml语言来描述的,所以它修改自如 
  • 矢量图色彩分辨率非常高清,同时支持滤镜 
  • 跨平台,因为矢量图是纯文本格式来描述的,所以不受平台的限制

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 值;
<string name="icons">&#x3605; &#x35ad; &#x35ae; &#x35af;</string>

4:打开 activity_main.xml,添加 string 值到 TextView:

 <TextView
    android:id="@+id/like"
    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文件中,我这里选择了购物车和删除图标,如下所示:

<string name="svg_cart">&#xe698;</string>
<string name="svg_delete">&#xe69d;</string>

3、然后我们在xml文件中新增一个TextView控件,文本内容引用购物车这个文本,代码如下:

<TextView
    android:id="@+id/tv_cart"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="50sp"
    android:textColor="@color/colorAccent"
    android:text="@string/svg_cart" />

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<String, Character> mChars;

    @Override
    public IIcon getIcon(String key) { //通过key拿到内部类中的Icon
        return Icon.valueOf(key);
    }

    @Override
    public HashMap<String, Character> getCharacters() { //将字符串存到HashMap中
        if (mChars == null) {
            HashMap<String, Character> 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<String> getIcons() { //返回一个有序集合
        Collection<String> 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字符的时候,需要将“&#x”替换为“\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
    android:id="@+id/iv_set"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/tv_qrcode"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"/>
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

好了,本篇要分享的东西就是这么多,欢迎大家留言探讨,多多批评指正!

发布了48 篇原创文章 · 获赞 47 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/JArchie520/article/details/79041376