概述
VectorDrawable是通过XML文件中的一系列点,线和曲线及其相关颜色信息定义的。 使用VectorDrawable的主要优点是图像可扩展性。 它可以缩放而不损耗显示质量,这意味着相同的文件被调整为不同的屏幕密度,而不会损耗图像质量。 从而得到较小的APK文件和较少的开发人员维护。 使用矢量图像可以进行动画,通过使用多个XML文件代替每个显示分辨率的多个图像。
让我们通过一个例子来了解好处。 尺寸为100×100dp的图像可以在较小的显示分辨率上呈现良好的质量。 在较大的设备上,应用可能需要使用400 x 400 dp版本的图片。 通常,开发人员创建资产的多个版本以适应不同的屏幕密度。 这种方法消耗更多的开发工作,并导致更大的APK,这需要更多的空间在设备上。
从Android 5.0(API级别21)开始,有两个类支持矢量图形作为可绘制资源:VectorDrawable和AnimatedVectorDrawable。 在Android 5.0(API级别21)之前,支持库23.2或更高版本提供对Vector Drawables和Animated Vector Drawables的全面支持。
注意:为了优化重绘图性能,为每个VectorDrawable创建一个位图缓存。 因此,引用相同的VectorDrawable意味着共享相同的位图缓存。 如果这些引用不同意相同的大小,在每次改变大小时位图将重新创建和重绘。 换句话说,如果VectorDrawable用于不同的大小,创建多个VectorDrawable更有效,每个大小一个。
关于 VectorDrawable 类
VectorDrawable定义了一个静态的drawable对象。 与SVG格式类似,每个矢量图形被定义为树的层次结构,它由path 和 group组成。 每个path包含对象轮廓的几何体,group包含转换的详细信息。 所有path的绘制顺序与XML文件中显示的顺序相同。
下面是一个VectorDrawable XML文件示例,在充电模式下呈现电池的图像。
android:height="24dp"
android:width="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
此XML呈现以下图像:
vector、group、path和clip-path标签的相关属性如下所示:
vector 标签 --- 用于定义VectorDrawable
android:name
定义此VectorDrawable的名称。
Animatable : No.
android:width
用于定义drawable的固有宽度。 支持所有尺寸单位,通常使用dp指定。
Animatable : No.
android:height
用于定义drawable的固有高度。 支持所有尺寸单位,通常使用dp指定。
Animatable : No.
android:viewportWidth
用于定义viewport空间的宽度。 viewport是绘制paths路径数据的虚拟画布。
Animatable : No.
android:viewportHeight
用于定义viewport空间的高度。 viewport是绘制paths路径数据的虚拟画布。
Animatable : No.
android:tint
定义drawable 的 tint 颜色。默认是没有 tint 颜色的
Animatable : No.
android:tintMode
定义tint的 Porter-Duff blending 模式,默认值为 src_in
Animatable : No.
android:autoMirrored
指示当布局方向为RTL(从右到左)时,drawable是否需要被镜像。
Animatable : No.
android:alpha
drawable的不透明度。
Animatable : Yes.
group 标签 --- 定义一组paths 或 subgroups,以及transformation信息。
transformations是在与viewport相同的坐标中定义。 并且按照缩放,旋转,然后平移的顺序应用transformations。
android:name
定义group的名称。
Animatable : No.
android:rotation
group的旋转角度。
Animatable : Yes.
android:pivotX
group缩放和旋转时的X轴参考点。 是在viewport空间中定义的(即在vector标签的viewportWidth范围中取值)。
Animatable : Yes.
android:pivotY
group缩放和旋转时的Y轴参考点。 是在viewport空间中定义的(即在vector标签中viewportHeight范围中取值)。
Animatable : Yes.
android:scaleX
X坐标上的缩放倍数。
Animatable : Yes.
android:scaleY
Y坐标上的缩放倍数。
Animatable : Yes.
android:translateX
X坐标上的平移量。 是在viewport空间中定义的(即在vector标签的viewportWidth范围中取值)。
Animatable : Yes.
android:translateY
Y坐标上的平移量。 是在viewport空间中定义的(即在vector标签中viewportHeight范围中取值)。
Animatable : Yes.
path 标签 --- 定义要绘制的路径。
android:name
定义path的名称。
Animatable : No.
android:pathData
使用与SVG path data中的“d”属性完全相同的格式定义path data。 是在viewport空间中定义的(即使用vector标签中viewportWidth 、viewportHeight范围中的值定义path data)。
Animatable : Yes.
android:fillColor
指定用于填充path的颜色。 可能是color,或者对于SDK 24+的color state list或gradient color。 如果此属性是动画属性,动画设置的任何值都将覆盖原始值。 如果未指定此属性,则不绘制path填充。
Animatable : Yes.
android:strokeColor
指定用于绘制path轮廓的颜色。 可能是color,或者对于SDK 24+的color state list或gradient color。 如果此属性是动画属性,动画设置的任何值都将覆盖原始值。 如果未指定此属性,则不绘制path轮廓。
Animatable : Yes.
android:strokeWidth
定义路径轮廓的宽度。
Animatable : Yes.
android:strokeAlpha
路径轮廓的不透明度。
Animatable : Yes.
android:fillAlpha
填充路径的不透明度。
Animatable : Yes.
android:trimPathStart
从路径起始位置截断路径的比例,取值范围从0到1
Animatable : Yes.
android:trimPathEnd
从路径结束位置截断路径的比例,取值范围从0到1
Animatable : Yes.
android:trimPathOffset
设置路径截取的范围 Shift trim region (allows showed region to include the start and end), 取值范围从0到1
Animatable : Yes.
android:strokeLineCap
设置路径轮廓线帽的形状:butt,round,square。体呈现的效果可以参考下图
Animatable : No.
android:strokeLineJoin
设置路径轮廓交界处的连接方式:miter,round,bevel。具体呈现的效果可以参考下图
Animatable : No.
android:strokeMiterLimit
Sets the Miter limit for a stroked path. 用来限制miterLengh和strokeWidth之间的比例,
两条直线之间的角度是锐角时。 miterLength和storeWidth之间的比例可以大于storeMiterLimit。
在这种情况下,两条直线之间的交点的形状将从“Miter-Join”改变为“Bevel-Join”。
具体具体呈现的效果可以参考下图。
Animatable : No.
android:fillType
设置路径的fillType。 类型可以是“ evenOdd”或“ nonZero”。 它们的行为与SVG的“fill-rule”属性相同。 有关更多详细信息,请参考(https://www.w3.org/TR/SVG/painting.html#FillRuleProperty)
Animatable : No.
clip-path 标签 --- 定义当前修剪的路径。 请注意,clip-path仅适用于当前group及其子项。
android:name
定义clip path的名称。
Animatable : No.
android:pathData
使用与SVG path data中的“d”属性相同的格式定义clip-path数据。
Animatable : Yes.
关于 AnimatedVectorDrawable 类
这个类使用ObjectAnimator或AnimatorSet定义的动画来动画VectorDrawable的属性。
从API 25开始,AnimatedVectorDrawable在RenderThread(而不是早期API的UI线程)上运行。 这意味着AnimatedVectorDrawable中的动画可以保持平滑,即使在UI线程上有重的工作负载。 注意:如果UI线程没有响应,RenderThread可以继续动画,直到UI线程能够推送另一个帧。 因此,不可能使用UI线程动画精确地协调支持RenderThread的AnimatedVectorDrawable。 另外,onAnimationEnd(Drawable)将在RenderThread上完成AnimatedVectorDrawable后调用该帧。
AnimatedVectorDrawable可以在三个单独的XML文件或一个XML中定义。
1> 多个XML文件的示例
以下XML文件演示了矢量图形的动画。
VectorDrawable's XML file: vd.xml
AnimatedVectorDrawable's XML file: avd.xml
Animator XML files that are used in the AnimatedVectorDrawable's XML file: rotation.xml and path_morph.xml
animated-vector和target标签的相关属性如下所示:
android:animation
引用作用于path、group或者vector drawable的动画
android:drawable
引用vector drawable资源
android:name
path、group或者vector drawable的名称
单个 XML 文件的示例
通过使用此方法,您可以通过XML Bundle Format将相关的XML文件合并为单个XML文件。 在构建应用程序时,aapt tag创建单独的资源,并在animated-vector中引用它们。 此方法需要构建工具24或更高版本,并且向后兼容。
Vector Drawables向后兼容性解决方案
下表总结了可用于向后兼容的两种技术:
1> PNG generation
Android 5.0(API级别21)和更高版本提供了vector drawable support。 如果您的应用程序的最低API级别较低,Vector Asset Studio会将vector drawable文件添加到您的项目中; 此外,在构建时,Gradle以各种分辨率创建PNG光栅(raster)图像。 Gradle生成由build.gradle文件中的Domain Specific Language (DSL) generatedDensities属性指定的PNG密度。
对于Android 5.0(API级别21)及更高版本,Vector Asset Studio支持所有VectorDrawable XML元素。 为了向后兼容Android 4.4(API级别20)及更低版本,Vector Asset Studio支持以下XML元素:
2> Support Library
为了在5.0(API级别21)之前的Android设备上支持Vector Drawable和Animated Vector Drawable,VectorDrawableCompat和AnimatedVectorDrawableCompat分别通过两个新的支持库提供:support-vector-drawable和animated-vector-drawable。
Android Studio 1.4在构建时通过生成PNG文件引入了对Vector Drawables的有限兼容性支持(就是上面第一种技术)。 Vector Drawable和Animated Vector Drawable支持库提供灵活性和广泛的兼容性 - 它是一个支持库,所以你可以使用它在Android 2.1(API级别7+)的Android平台。 要将应用程序配置为使用Vector支持库,请将vectorDrawables元素添加到app module中的build.gradle文件中。
使用以下代码片段配置vectorDrawables元素:
//For Gradle Plugin 2.0+
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
//For Gradle Plugin 1.5 or below
android {
defaultConfig {
// Stops the Gradle plugin’s automatic rasterization of vectors
generatedDensities = []
}
// Flag notifies aapt to keep the attribute IDs around
aaptOptions {
additionalParameters "--no-version-vectors"
}
}
您可以在API 11和更高版本的设备上使用VectorDrawableCompat和AnimatedVectorDrawableCompat。Android加载Drawable的方式中不是接受可绘制ID的每个地方(例如在XML文件中)都支持加载Vector Drawable。 值得庆幸的是,AppCompat添加了许多功能,使其易于使用Vector Drawable。 首先,当使用ImageView(或子类,如ImageButton和FloatingActionButton)时,你将能够使用新的app:srcCompat属性来引用Vector Drawable以及任何其他地方使用android:src属性:
要在运行时更改Drawable时,可以像以前一样使用setImageResource()方法。 使用AppCompat和app:srcCompat将Vector Drawable集成到应用程序中是最简单的方法。
支持库限制
Animated Vector Drawable在API 21之前的平台上运行时可以做什么样的事情有一些限制。下面的列表解释了与支持库不兼容的功能:
Path Morphing (PathType evaluator) :用于将一个路径变形为另一个路径。
Path Interpolation :通过定义一个灵活的插值器(表示为路径)来代替像LinearInterpolator这样的系统定义的插值器。
Move along path :几何对象可以作为动画的一部分在任意路径上移动。
举例说明
1> path标签的trimPathStart和trimPathEnd属性的动画
先来看一下效果图:
实现代码如下:
VectorDrawable's XML file:vd_trim_path_searchbar.xml
AnimatedVectorDrawable's XML file: avd_trim_path_searchbar.xml
Animator XML files that are used in the AnimatedVectorDrawable's XML file: anim_trim_path_searchbar_in.xml and anim_trim_path_searchbar_out.xml
anim_trim_path_searchbar_in.xml
anim_trim_path_searchbar_out.xml
在代码中配置并且开启动画:
Drawable drawable = imageView.getDrawable();
if (drawable instanceof Animatable) {
((Animatable) drawable).start();
}
2> path标签或者group标签的pathData属性动画(即Path Morphing动画,只支持Android L+ 版本)
例1 : 先来看一下效果图:
实现代码如下:
VectorDrawable's XML file:vd_path_paw.xml
AnimatedVectorDrawable's XML file: avd_path_paw.xml
Animator XML files that are used in the AnimatedVectorDrawable's XML file: anim_path_morph_toe1.xml 、anim_path_morph_toe2.xml、anim_path_morph_toe3.xml and anim_path_morph_toe4.xml
anim_path_morph_toe1.xml
anim_path_morph_toe2.xml
anim_path_morph_toe3.xml
anim_path_morph_toe4.xml
在代码中配置并且开启动画:
AnimatedVectorDrawable animatedVectorDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.avd_path_paw);
imageView.setImageDrawable(animatedVectorDrawable);
if (animatedVectorDrawable != null) {
animatedVectorDrawable.start();
}
例2 : 先来看一下效果图:
实现代码如下:
VectorDrawable's XML file:vd_path_heart.xml
AnimatedVectorDrawable's XML file: avd_path_heart_empty.xml and avd_path_heart_full.xml
avd_path_heart_empty.xml
avd_path_heart_full.xml
Animator XML files that are used in the AnimatedVectorDrawable's XML file: anim_heart_empty.xml and anim_heart_full.xml
anim_heart_empty.xml
anim_heart_full.xml
在代码中配置并且开启动画:
AnimatedVectorDrawable emptyToFull = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.avd_path_heart_full);
AnimatedVectorDrawable fullToEmpty = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.avd_path_heart_empty);
AnimatedVectorDrawable animDrawable = isEmpty ? fullToEmpty: emptyToFull;
imageView.setImageDrawable(animDrawable);
if (animDrawable != null) {
animDrawable.start();
}
isEmpty = !isEmpty;
参考文档
Add Multi-Density Vector Graphics
Vector Drawable
VectorDrawable XML相关标签属性说明
AnimatedVectorDrawable XML相关标签属性说明