SVG学习--VectorDrawable的使用
SVG的全称是Scalable Vector Graphics,叫可缩放矢量图形。它和位图(Bitmap)相对,SVG不会像位图一样因为缩放而让图片质量下降。它的优点在于节约空间,使用方便
Android 5.0中引入了 VectorDrawable 来支持矢量图(SVG),同时还引入了 AnimatedVectorDrawable 来支持矢量图动画,在最近几次Support包更新之后,SVG的兼容性问题得以大大改善
基于以上所述,是时候了解一下SVG的实现了
SVG图片的加载
AS本身就支持SVG的加载,右击drawable,通过Vector Asset直接加载一个SVG图像
打开SVG选择 选择一张AS自带的SVG图片
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>
初步解释一下标签的含义
android:width/android:height: 这个无需多说,这个是整个图片的宽高
android:viewportWidth/android:viewportHeight: 画布大小。这个值最好与android:width/android:height保持一致,因为android:pathData使用的坐标系范围与他相关。在宽高不会改变的情况下,改变SVG自身内部坐标系的大小,造成图片的偏移与缩放
android:fillColor: SVG路径的填充色
android:pathData: SVG路径
乍一看这个路径描述的内容我们看的一头雾水,我们一步一步来,学习完基本概念,就能很轻松的理解了
pathData命令
pathData命令一般由字母跟数字组成,字母多为命令关键字(这里有个大小写的区别,大写的字母是基于原点坐标系的偏移量,即绝对位置;小写字母是基于当前点坐标系的偏移量,即相对位置),数字多为坐标,
M(x y): 没什么好说的,移动画笔到指定点,并不进行绘制,默认在(0,0)点。与Paint里面moveTo可以理解成一样的概念
**L(l) (x y) **: 就是直接画一条线了,与它类似的有H(h)跟V(v)。这里有一个方向的概念,pathData中的方向与View绘制的方向是一样的。H就是画一条横线,V就是画一条竖线,L就是画点到点之间的线
Z: 没有参数,就是连接起点跟终点
A(rx ry x-axis-rotation large-arc-flag sweep-flag x y): 绘制圆弧。里面的参数比较多,
rx\ry 是椭圆在X\Y轴的半径
x-axis-rotation 是X轴旋转角度
large-arc-flag 0表示取小弧度,1表示取大弧度(这个通过下图可以理解)
sweep-flag 0表示逆时针方向,1表示顺时针方向
我们继续上一张图看看
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/colorPrimary"
android:pathData="M12,12 a4,6 0 1 1 3,4"/>
<path
android:fillColor="@android:color/holo_green_light"
android:pathData="M12,12 a4,6 0 0 1 3,4"/>
<path
android:fillColor="@android:color/holo_purple"
android:pathData="M12,12 a4,6 0 1 0 3,4"/>
<path
android:fillColor="@android:color/holo_orange_light"
android:pathData="M12,12 a4,6 0 0 0 3,4"/>
</vector>
这里绘制了半径为4dp、6dp的椭圆,椭圆上有2点(12,12)与(15,16),按照大圆弧小圆弧顺逆时针方向4种状态
A(rx ry x-axis-rotation large-arc-flag sweep-flag x y)Q(x1 y1 x y): 二次贝塞尔曲线。在之前的文章里面,我已经说过贝塞尔曲线的概念,如果还不是很了解,请参阅利用属性动画,实现简单的爱心气泡点赞效果一文所涉及到的相关知识。这里(x1, y1)是控制点的坐标,(x,y)是终点坐标。还有一个类似的T指令,他只有终点参数可以设置,他的控制点被默认为上一次的控制点关于上次终点的中心对称点,比如上一次的控制点P1是(6,6),终点P2是(8,10), 那么使用T指令后默认控制点P1`为(10,14)。
<path android:strokeColor="@android:color/holo_red_dark"
android:strokeWidth="0.1"
android:pathData="M12,12 Q 14,14 18,13">
</path>
Q(x1 y1 x y)
C(x1 y1 x2 y2 x y): 三次贝塞尔曲线。同二阶一样,前2个坐标为2个控制点的坐标,最后一个为终点坐标。这里还有一个S指令,同T指令功能相同,就是上一次最后一个控制点相对上次的终点的中心对称点
<path android:strokeColor="@android:color/holo_red_dark"
android:strokeWidth="0.1"
android:pathData="M12,12 C 14,14 18,13 20,8">
</path>
C(x1 y1 x2 y2 x y)
至此,我们就把SVG涉及到画图的部分学习完了,我们再回过头来看看刚才的drawable是怎么实现的
+号的实现同样是一笔一笔的用L\H\V组合而成
投机取巧
给大家一个网址阿里巴巴矢量图标库,这个里面可以下载好web版本的SVG图片,然后我们将其拷贝到Android SVG to VectorDrawable,这样我们就能大致获取到各种素材的SVG图片了
注意事项
以上写法在android 5以上是没有任何问题的,但是放到之前版本上就会出现问题,看看之前的圆弧
Paste_Image.png原本是彩色的,在这里变成黑色的了。。。怎么办?
1 在build.gradle里面进行配置
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
|
2 只能用于AppCompatImageView或者AppCompatImageButton或其子类,而且必须在app:srcCompat标签中使用。
这样是肯定没有问题的,但是问题在于,我不可能把代码里面所有View都改成这2种。。。
3 SVG图像需要依附于StateListDrawable,InsetDrawable,LayerDrawable,LevelListDrawable,RotateDrawable,这样就可以在低版本中显示了。StateListDrawable最简单,就是直接写一个selector即可
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_a"></item>
</selector>
别忘记还有一个标志位要开启,在activity的最上方
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
这样就没问题了
4 换色
如果你想手动更换图片的背景色,那么只要这样就可以了
VectorDrawableCompat a=VectorDrawableCompat.create(getResources(), R.drawable.ic_a, getTheme());
a.setTint(Color.RED);
ImageView imageview= (ImageView) findViewById(R.id.imageview);
imageview.setImageDrawable(a);
Paste_Image.png
如何手动更换某一部分Path的色值,我暂时还不知道,如果你知道,请告诉我
参考文章
Android vector 标签 pathData 详解
关于android中矢量图如何用,有坑,爬坑,如何替代的另一些看法