Android AnimatedVectorDrawable
在本教程中,我们将讨论AnimatedVectorDrawable并在我们的android应用程序中以各种方式实现它。
了解VectorDrawables将使下面的文章更容易理解。
AnimatedVectorDrawable
自API 21以来就引入了AnimatedVectorDrawable类,该类可用于轻松漂亮地对Vector Drawables进行动画处理。
以下是您可以使用AnimatedVectorDrawable执行的一些操作:
旋转,缩放,平移VectorDrawables
对VectorDrawable进行动画处理,例如填充颜色等。
绘制路径并进行路径变形
通常,要为Vector Drawable设置动画,我们使用ObjectAnimator类定义动画。
ShapeShifter是一种流行的工具,可以直观地创建AnimatedVectorDrawable。
为此,我们需要导入Vector Asset/SVG文件。
我们有一个名为ic_settings.xml的示例矢量可绘制xml文件,如下所示:
<vector android:height="24dp" android:tint="#E5496D" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp" xmlns:android="https://schemas.android.com/apk/res/android"> <path android:fillColor="#FF000000" android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z" </vector>
让我们将其导入ShapeShifter中以创建AnimatedVectorDrawable:
首先,我们需要在组图层中添加矢量drawable以便向其中添加动画。
我们将可绘制矢量设置为旋转270度。
您必须设置VectorDrawable将围绕其旋转的ivotX和pivotY。
VectorDrawable的背景颜色并非总是正确地导入ShapeShifter中。
因此,您需要在此处再次设置。
以下是可以在AnimatedVectorDrawable上设置的一些属性:
- 回转
- X轴
- 枢轴
- 标度X
- 比例尺
- 翻译X
- 翻译
- pathData
- 填色
- strokeColor
- strokeWidth
- 笔画
- fillAlpha
- trimPathStart
- trimPathEnd
- trimPathOffset
现在,从ShapeShifter中,单击"导出– AnimatedVectorDrawable"以生成AnimatedVectorDrawable的xml版本:
ʻavd_settings.xml`
<animated-vector xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:aapt="https://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="settings_icon"
android:width="48dp"
android:height="48dp"
android:viewportHeight="24"
android:viewportWidth="24">
<group android:name="animate_vector">
<path
android:name="gear"
android:fillColor="#FF000000"
android:pathData="@string/settings_path"
</group>
</vector>
</aapt:attr>
<target android:name="animate_vector">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:duration="800"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="rotation"
android:repeatCount="infinite"
android:repeatMode="restart"
android:valueFrom="0"
android:valueTo="270"
android:valueType="floatType"
<objectAnimator
android:duration="800"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pivotX"
android:valueFrom="12"
android:valueTo="12"
android:valueType="floatType"
<objectAnimator
android:duration="800"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pivotY"
android:valueFrom="12"
android:valueTo="12"
android:valueType="floatType"
</set>
</aapt:attr>
</target>
</animated-vector>
我们已在strings.xml文件中将长路径数据设置为字符串资源。
AnimatedVectorDrawable中的" target"元素的name属性对应于动画组的名称。
animation属性采用了animator类,在此是对象animator。
为了使AnimatedVectorDrawable永久动画,我们在ObjectAnimator标记中为无限添加了repeatCount。
现在我们有了AnimatedVectorDrawable,我们可以通过以下方法在ImageView(任何相关视图)上进行设置:ʻandroid:src =" @ drawable/avd_settings""。
仍可绘制动画的矢量可绘制动画!
为了使其具有动画效果,我们需要执行以下操作:
Animatable animatable = imageView.getDrawable(); animatable.start();
动画表是一个接口,其中包含处理可绘制对象上的动画的方法。
像–start(),stop(),isRunning()之类的方法
以编程方式设置AnimatedVectorDrawable
AnimatedVectorDrawableCompat animatedVectorDrawableCompat = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_settings); imageView.setImageDrawable(animatedVectorDrawableCompat);
这是上下文。
除了可以在单个xml文件中创建可绘制的整个动画矢量之外,我们还可以分别设置对象或者动画制作者。
在以下部分中,我们将创建不同类型的AnimatedVectorDrawable
项目结构
不要忘记在应用的build.gradle中启用向量支持:
android {
...
defaultConfig {
...
vectorDrawables.useSupportLibrary = true
...
}
...
}
代码
下面给出了activity_main.xml布局的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imgSettings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="4dp"
app:srcCompat="@drawable/avd_settings"
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabSync"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:backgroundTint="@android:color/white"
<ImageView
android:id="@+id/imgJD"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="4dp"
app:srcCompat="@drawable/avd_jd"
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabTickCross"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:backgroundTint="@android:color/white"
android:src="@drawable/ic_tick"
</LinearLayout>
我们已经看过avd_settings.xml文件。
接下来看avd_jd.xml。
我们编写的ic_jd.xml是:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="https://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0">
<group android:name="thing">
<path
android:name="Dev"
android:pathData="M 25 10 L 12 10 M 25 10 L 25 30 M 25 30 C 20 35 15 30 12 25"
android:strokeColor="#000"
android:strokeWidth="1"
<path
android:name="Journal"
android:pathData="M 30 10 L 30 30 M 30 10 C 45 15 45 25 30 30"
android:strokeColor="@android:color/holo_red_dark"
android:strokeWidth="1"
</group>
</vector>
从ShapeShifter生成的avd_jd.xml代码为:
<animated-vector
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:aapt="https://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="148dp"
android:height="148dp"
android:viewportWidth="48"
android:viewportHeight="48">
<group android:name="theitroad">
<group
android:name="group_j"
android:pivotX="24"
android:pivotY="24"
android:rotation="270">
<path
android:name="journal"
android:pathData="M 25 10 L 12 10 M 25 10 L 25 30 M 25 30 C 20 35 15 30 12 25"
android:strokeColor="#000000"
android:strokeWidth="1"
</group>
</group>
<group
android:name="group_d"
android:pivotX="24"
android:pivotY="24"
android:translateX="10"
android:scaleX="0.5"
android:scaleY="0.5">
<path
android:name="dev"
android:pathData="M 30 10 L 30 30 M 30 10 C 45 15 45 25 30 30"
android:strokeColor="#000000"
android:strokeWidth="1"
</group>
</vector>
</aapt:attr>
<target android:name="group_d">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="translateX"
android:duration="400"
android:valueFrom="10"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"
<objectAnimator
android:propertyName="scaleX"
android:duration="600"
android:valueFrom="0.5"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"
<objectAnimator
android:propertyName="scaleY"
android:duration="600"
android:valueFrom="0.5"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"
</set>
</aapt:attr>
</target>
<target android:name="group_j">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="rotation"
android:startOffset="100"
android:duration="500"
android:valueFrom="270"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"
</aapt:attr>
</target>
<target android:name="journal">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="strokeColor"
android:startOffset="600"
android:duration="200"
android:valueFrom="#000000"
android:valueTo="#cc0000"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"
</aapt:attr>
</target>
</animated-vector>
在上面的XML代码中,我们分别在两条路径上进行了缩放,动画和旋转。
注意,每个路径都有一个name属性,该属性链接到各自的目标。
XML属性是不言自明的。
一旦掌握了这些,就可以直接编写AnimatedVectorDrawable XML代码,而无需使用ShapeShifter。
avd_cross2tick.xml和avd_tick2cross.xml用于将可绘制的刻度线向量转换为可绘制的交叉向量。
因此,它改变了路径。
对象动画师的代码分别放在res目录中的动画师文件夹中。
您可以在本教程结尾的源代码/Github存储库中找到它们的完整实现。
由于篇幅所限,我们忽略了这一点。
MainActivity.java的代码如下:
package com.theitroad.androidanimatedvectordrawable;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.design.widget.FloatingActionButton;
import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private AnimatedVectorDrawable tickToCross, crossToTick;
private boolean isTick = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton fabSync = findViewById(R.id.fabSync);
FloatingActionButton fabTickCross = findViewById(R.id.fabTickCross);
tickToCross = (AnimatedVectorDrawable) getDrawable(R.drawable.avd_tick2cross);
crossToTick = (AnimatedVectorDrawable) getDrawable(R.drawable.avd_cross2tick);
ImageView imgSettings = findViewById(R.id.imgSettings);
ImageView imgJD = findViewById(R.id.imgJD);
imgSettings.setOnClickListener(this);
imgJD.setOnClickListener(this);
AnimatedVectorDrawableCompat animatedVectorDrawableCompat = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_sync);
fabSync.setImageDrawable(animatedVectorDrawableCompat);
fabSync.setOnClickListener(this);
fabTickCross.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.imgSettings:
Animatable animatable = (Animatable) ((ImageView) view).getDrawable();
if (animatable.isRunning())
animatable.stop();
else
animatable.start();
break;
case R.id.imgJD:
animatable = (Animatable) ((ImageView) view).getDrawable();
if (animatable.isRunning())
animatable.stop();
else
animatable.start();
break;
case R.id.fabSync:
animatable = (Animatable) ((FloatingActionButton) view).getDrawable();
if (animatable.isRunning())
animatable.stop();
else
animatable.start();
break;
case R.id.fabTickCross:
AnimatedVectorDrawable drawable = isTick ? tickToCross : crossToTick;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
drawable.registerAnimationCallback(new Animatable2.AnimationCallback() {
@Override
public void onAnimationStart(Drawable drawable) {
super.onAnimationStart(drawable);
}
@Override
public void onAnimationEnd(Drawable drawable) {
super.onAnimationEnd(drawable);
}
});
}
FloatingActionButton fab = ((FloatingActionButton) view);
fab.setImageDrawable(drawable);
drawable.start();
isTick = !isTick;
break;
}
}
}
其中我们在两个ImageView和两个FloatingActionButtons上设置了AnimatedVectorDrawable。
为了收听动画的开始和结束,我们可以在AnimatedVectorDrawable上注册动画回调:
drawable.registerAnimationCallback(new Animatable2.AnimationCallback() {
@Override
public void onAnimationStart(Drawable drawable) {
super.onAnimationStart(drawable);
}
@Override
public void onAnimationEnd(Drawable drawable) {
super.onAnimationEnd(drawable);
}
});
注意:registerAnimationCallback仅适用于Android M(23)及更高版本。

