Vector
优势VectorDrawable
主要有两个优势:屏幕自适应和体积小。android
png
或者jpg
图片,那么为了能让图片在不一样分辨率的机型上可以很好地展示,一般会在各个drawable
文件夹下放置不一样分辨率大小的图片文件,而VectorDrawable
则不须要,仅仅只使用一套资源,就可以适应任何分辨率的手机。VectorDrawable
素材的大小要比png
和jpg
小不少。SVG
和Vector
的基本概念下面,咱们先介绍一下SVG
和VectorDrawable
的基本概念:缓存
SVG
:它并非Android
平台特有的概念,它的全称为可缩放矢量图形,简单的来讲,就是用于描述二维矢量图形的图形格式,更加详细的解释能够参考:SVG - 百度百科。VectorDrawable
:它是Android
当中的SVG
实现,它并不支持SVG
的所有语法,只是支持部分有必要的部分。VectorDrawable
俗话说的好,巧妇难为无米炊,这一节咱们就来介绍一下如何得到一个VectorDrawable
,通常获取的方式有如下三种方式:bash
SVG
素材,再经过工具转换成为VectorDrawable
Android Studio
中的素材库,直接获取VectorDrawable
Vector
的语法,本身描述SVG
素材,再经过工具转换成为VectorDrawable
首先获取SVG
素材,再将它转换成为VectorDrawable
是最经常使用的方式,而SVG
素材的获取又有如下几种途径:app
SVG
图像UI
设计师使用专业的工具导出png
和jpg
素材转换为SVG
图像对于我的开发者而言,通常都会采用第一种方式,咱们这里也只介绍第一种方式。不少文章都推荐过这个网站:iconFront - 阿里巴巴,它提供了SVG
和PNG
素材的直接下载: eclipse
Android Studio
的
New
选项中,选择
Vector Asset
:
Local file
,并打开咱们下载后的图像,再选择
next
保存到指定的文件夹:
*.xml
文件,这个就是
VectorDrawable
:
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="1024.0"
android:viewportWidth="1024.0"
android:width="24dp">
<path android:fillColor="#FF000000"
android:pathData="M887.9,298.2c-12.9,-12.1 -33.2,-11.5 -45.2,1.4L415.9,754l-233.1,-229.7C170.2,511.9 150,512 137.5,524.6c-12.4,12.6 -12.3,32.9 0.4,45.2l256.5,252.7c0.1,0.1 0.2,0.1 0.3,0.2 0.1,0.1 0.1,0.2 0.2,0.3 2,1.9 4.4,3 6.8,4.3 1.2,0.7 2.1,1.7 3.4,2.1 3.8,1.5 7.8,2.2 11.7,2.2 4.2,0 8.4,-0.8 12.3,-2.5 1.3,-0.5 2.3,-1.7 3.6,-2.4 2.4,-1.4 4.9,-2.6 6.9,-4.7 0.1,-0.1 0.1,-0.3 0.2,-0.4 0.1,-0.1 0.2,-0.1 0.3,-0.2l449.2,-478.2C901.4,330.6 900.8,310.3 887.9,298.2z"/>
</vector>
复制代码
Android Studio
中的素材库,直接获取VectorDrawable
仍是在上面的那个界面,咱们勾选另一个选项: ide
Material Design
提供的素材库:
*.xml
的
VectorDrawable
:
<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="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>
复制代码
Vector
的语法,本身描述在3.1
和3.2
当中,咱们能够看到,最终VectorDrawable
都是用一个*.xml
来表示的,那么,咱们固然能够根据SVG
的语法,来编写一个xml
文件,经过pathData
属性进行描述,不过这种方式较为繁琐,通常不会采用。工具
Vector
语法虽说大多数状况下,咱们不会彻底手动去编写Vector
的xml
文件,可是,对于Vector
的基本语法仍是有必要了解一些的,由于在咱们后边谈到的动态Vector
中须要了解对于每一个标签有哪些属性能够设置,Vector
包含下面三种标签:布局
<vector>
<group>
<path>
<path>
</group>
</vector>
复制代码
<vector>
标签name
:矢量图的名字width, height
:矢量图的固有宽高,一般使用dp
。viewportWidth, viewportHeight
:把矢量图的宽高分红多少个单元,这里的每一个单元就对应pathData
中的一个点坐标。<path>
标签name
:路径的名称。fillColor
:图形的填充颜色。pathData
:定义控制点的位置,相似与Canvas
当中的Path
类。<group>
标签<group>
用来把多个<path>
组合在一块儿,进行相同的处理。性能
更多的属性能够查阅下面这两篇文章:gradle
VectorDrawable 详解 Android 中的 SVG 图像的各个属性意义
Vector
的兼容性问题为了让VectorDrawable
可以在Android 5.0
如下版本的手机上使用,咱们须要引入support
包,并修改gradle
的配置。
support
包VectorDrawable
是在Android 5.0
以后提出来的,所以,若是咱们须要在低版本上使用,那么就要引入com.android.support:appcompat-v7
包,要求版本号大于等于23.2.0
,这里咱们选用的是:
compile 'com.android.support:appcompat-v7:25.3.1'
复制代码
与Vector
相关的两个包为:
gradle
配置文件若是**gradle
的版本小于2.0
**:
android {
defaultConfig {
generatedDensities = []
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
}
复制代码
若是**gradle
的版本大于2.0
**,例如咱们所用的版本:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
}
}
复制代码
那么须要这样配置:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
复制代码
关于更多兼容性的问题,能够查看下面这篇文章
VectorDrawable
若是使用静态的方式展现VectorDrawable
,那么很简单,只须要像使用普通的drawable
同样,首先,咱们按照第三节的方法,获取到一个vectorDrawable
,并把它放在drawable
文件夹下:
<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="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>
复制代码
咱们能够应用于:
ImageView
的src
View
的background
TextView
的drawable
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/iv_static"
android:layout_width="50dp"
android:layout_height="50dp"
android:clickable="true"
android:src="@drawable/ic_account_circle_selector"/>
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:clickable="true"
android:background="@drawable/ic_account_circle_selector"/>
<TextView
android:drawableStart="@drawable/ic_account_circle_black_24dp"
android:text="UserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
复制代码
在上面的例子中,咱们还使用了ic_account_circle_selector
,其定义以下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_account_circle_black_24dp" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_account_circle_black_normal_24dp"/>
</selector>
复制代码
ic_account_circle_black_24dp
就是以前获取到的素材,而ic_account_circle_black_normal_24dp
就是改变了它的fillColor
属性:
<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="#80000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>
复制代码
点击后的效果为:
VectorDrawable
动态的VectorDrawable
,也就是AnimatedVectorDrawable
,通常来讲,它的整个结构以下图所示:
VectorDrawable
,通常须要提供三种类型的
*.xml
文件,这三个
xml
文件的根标签分别为:
vector
:图像资源,也就是咱们上面讨论的静态vector
,定义于res/drawable
文件夹下。objectAnimator
:定义图像资源中个元素的动画行为,定义于res/anim
文件夹下。animated - vector
:对vector
中的元素与objectAnimator
进行组合,定义于res/drawable
文件夹下。<group>
标签进行动画下面,咱们先看一个简单的例子,上面咱们所谈到的三个*.xml
文件以下:
vector
文件<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<group android:name="group_account" android:pivotX="12" android:pivotY="12">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</group>
</vector>
复制代码
这里咱们生成了一个头像的Vector
素材,它的图像以下,注意到,咱们用一个group
标签把path
标签包裹起来,而且给它定义了一个name
属性为group_account
,这个属性在后面会用到。
objectAnimator
文件<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="500"
android:propertyName="rotation"
android:repeatCount="infinite"
android:valueFrom="0"
android:valueTo="360"/>
</set>
复制代码
objectAnimator
的定义和属性动画是相同的,咱们须要指定须要变换的属性,也就是propertyName
,并经过valueFrom/valueTo
指定变化的起点值和终点值,这里咱们选择了采用无限循环的方式来变换目标的rotation
属性。
animated-vector
文件<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/account_vector">
<target
android:animation="@anim/account_object_animator"
android:name="group_account"/>
</animated-vector>
复制代码
animated-vector
和vector
是一一对应的关系,所以须要在根标签中指定android:drawable
,也就是在7.1.1
中的vector
文件。 而每个target
标签是内是成对的name - animation
属性,name
就是在7.1.1
中声明的group
的name
,而animation
则是在7.1.2
中定义的动画文件。
若是objectAnimator
所指定的属性在name
所对应的标签中没有,那么不会发生任何变化。
首先,在布局的xml
文件中,把imageView
的src
指定为7.1.3
中的animate-vector
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/iv_dynamic"
android:src="@drawable/account_animated_vector"
android:text="UserName"
android:layout_width="50dp"
android:layout_height="50dp"/>
</LinearLayout>
复制代码
在代码中,须要手动得到这个vectorDrawable
,而后启动动画:
public class VectorDrawableActivity extends AppCompatActivity {
private ImageView mAnimateView;
private AnimatedVectorDrawable mAnimatedVectorDrawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vector_drawable);
mAnimateView = (ImageView) findViewById(R.id.iv_dynamic);
mAnimatedVectorDrawable = (AnimatedVectorDrawable) mAnimateView.getDrawable();
mAnimateView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAnimatedVectorDrawable.start();
}
});
}
}
复制代码
效果以下:
<path>
标签中的属性进行动画在7.1
中,演示了如何对group
标签的属性进行变换,下面,咱们再演示一下如何对path
标签中的属性进行变换。和前面相似,咱们依然须要三种类性的*.xml
文件
vector
文件<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:name="path_check"
android:fillColor="#FF000000"
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>
复制代码
这里,一样须要给path
指定一个名字,用于后面和objectAnimator
进行关联,它的素材为:
objectAnimator
文件<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="500"
android:propertyName="trimPathEnd"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"/>
</set>
复制代码
这里,咱们选择的是path
标签下的trimPathEnd
属性,它表示从Path
终点的位置去除Path
,与之对应的还有trimPathStart
属性,它表示从Path
起点的位置去除Path
,而trimPathOffset
则能够改变Path
的起点,这三个值的取值范围都是0~1
。
animated-vector
文件<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/check_vector">
<target
android:animation="@anim/check_object_animator"
android:name="path_check"/>
</animated-vector>
复制代码
效果以下:
<path>
之间切换除了上面普通的属性以外,还支持对<path>
标签下的<pathData>
进行改变,系统会比较两个pathData
之间的差异,并自动产生合适的动画。须要注意,它要求这两个pathData
的点坐标的个数是相同的。
Vector
文件这里,咱们须要生成两个vectorDrawable
,首先是起始的VectorDrawable
:
<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:name="path_arrow_down"
android:fillColor="#FF000000"
android:pathData="M7,10l5,5 5,-5z"/>
</vector>
复制代码
它的素材为:
VectorDrawable
:
<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="M7,14l5,-5 5,5z"/>
</vector>
复制代码
它对应的素材为:
objectAnimator
文件<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="500"
android:propertyName="pathData"
android:valueFrom="M7,10l5,5 5,-5z"
android:valueTo="M7,14l5,-5 5,5z"
android:valueType="pathType"/>
</set>
复制代码
这里的propertyName
和valueType
须要分别定义为pathData
和pathType
,而起点和终点的值就是咱们在7.3.1
生成的两个VectorDrawable
所对应的pathData
属性的值。
animated-vector
文件<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/arrow_down_vector">
<target
android:animation="@anim/arrow_down_object_animator"
android:name="path_arrow_down"/>
</animated-vector>
复制代码
最终的效果为:
VectorDrawable
的性能关于VectorDrawable
的性能问题,Android Vector 曲折的兼容之路 这篇文章说的很好,所以直接引用过来了:
Bitmap
的绘制效率并不必定会比Vector
高,它们有必定的平衡点,当Vector
比较简单时,其效率是必定比Bitmap
高的,因此,为了保证Vector
的高效率,Vector
须要更加简单,PathData
更加标准、精简,当Vector
图像变得很是复杂时,就须要使用Bitmap
来代替了。
Vector
适用于ICON
、Button
、ImageView
的图标等小的ICON
,或者是须要的动画效果,因为Bitmap
在GPU
中有缓存功能,而Vector
并无,因此Vector
图像不能作频繁的重绘Vector
图像过于复杂时,不只仅要注意绘制效率,初始化效率也是须要考虑的重要因素SVG
加载速度会快于PNG
,但渲染速度会慢于PNG
,毕竟PNG
有硬件加速,但平均下来,加载速度的提高弥补了绘制的速度缺陷。1. Android Vector 曲折的兼容之路 2. VectorDrawable 怎么玩 3. Android 使用矢量图(SVG, VectorDrawable)实践篇 4. SVG - 百度百科 5. Android 中的 SVG 图像的各个属性意义