Android animator-vector 矢量动画制作过程
起因:最近有个需求,就是拍摄时,点击拍摄图标,然后图标要变成另外一个图案。我做完功能先拿给UI设计师看,他说图标能不能不要突然变化,要有个渐变的过程。然后拿了个app中的例子给我看。看完后我就想到了大概要用什么方式实现矢量动画,但是仅仅是用什么方式实现,具体怎么实现,一窍不通。花了两天时间,通过查找各种资料,以及动手做一个demo,最后明白了矢量动画到底怎么做。
网上找的资料其实说的挺全的,但是我这人有个毛病,不是一笔一划的写出来,和理解透,我就不可能做出来。为了帮助他人,我把制作这个动画的思路,过程,和一些注意点记录下来,万一有人看了,希望不要像我一样看两天。
另外这矢量图还有些适配问题,需要另外找找资料看
1.相关参考文章知识点及工具
(我就不班门弄斧了,大佬们写的很细)
1. 矢量动画的获取工具:Android studio Vector Asset
2.path路径匹配工具 :http://www.apkbus.com/thread-256367-2-1.html
3.矢量的介绍及画法:http://blog.csdn.net/easyer2012/article/details/52618228
4.矢量的介绍及画法2:https://www.2cto.com/kf/201606/515280.html
2.先给看下结果
ezgif.com-video-to-gif(1).gif哈哈!做完这个反正我是挺高兴的,虽然感觉里边还有挺多内容还不知道,回去我再多做几个理解下。
3.正式开始
3.1 矢量底图的获取
通过 Android studio自带的矢量图片制作工具获取现成的矢量图,如果你乐意自己画也可以,规则请参考制作工具3,4两条,这个工具需要你的源文件是SVG 或者 psd格式的,请各位注意。
Paste_Image.png这是获取完之后的图片
Paste_Image.png上图的代码:res\drawable\button_ready.xml
<vector android:height="100dp" android:viewportHeight="218"
android:viewportWidth="218" android:width="100dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillAlpha="0.5"
android:fillColor="#000"
android:name="椭圆 10 拷贝 2"
android:pathData="m109.5 5c57.71 0 104.5 46.79 104.5 104.5c0 57.71 -46.79 104.5 -104.5 104.5c-57.71 0 -104.5 -46.79 -104.5 -104.5c0 -57.71 46.79 -104.5 104.5 -104.5z"/>
<path
android:fillColor="#fff"
android:name="c1"
android:pathData="m109 16c51.36 0 93 41.64 93 93c0 51.36 -41.64 93 -93 93c-51.36 0 -93 -41.64 -93 -93c0 -51.36 41.64 -93 93 -93zm0 -16c-60.2 0 -109 48.8 -109 109c0 60.2 48.8 109 109 109c60.2 0 109 -48.8 109 -109c0 -60.2 -48.8 -109 -109 -109z"/>
<path
android:fillColor="#ff2f51"
android:name="c2"
android:pathData="@string/round1"/>
</vector>
看到没有很神奇吧,仔细看源码pathData就是描述怎么画这些图。文中有三个Path,通过左边的颜色你也可以知道,这个矢量图是画了三个部分.
根据效果图来看,我们是想让中间红色部分有动效,所以先把 红色部分的PathData提取出来备用,
上图的代码:res\drawable\button_record.xml
<vector android:height="100dp" android:viewportHeight="218"
android:viewportWidth="218" android:width="100dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillAlpha="0.5"
android:fillColor="#000"
android:name="椭圆 10 拷贝 3"
android:pathData="m109.5 11c54.4 0 98.5 44.1 98.5 98.5c0 54.4 -44.1 98.5 -98.5 98.5c-54.4 0 -98.5 -44.1 -98.5 -98.5c0 -54.4 44.1 -98.5 98.5 -98.5z"/>
<path
android:fillColor="#ff2f51"
android:name="c3"
android:pathData="@string/square1"/>
<path
android:fillColor="#fff"
android:name="椭圆 10 拷贝 5"
android:pathData="m109 16c51.36 0 93 41.64 93 93c0 51.36 -41.64 93 -93 93c-51.36 0 -93 -41.64 -93 -93c0 -51.36 41.64 -93 93 -93zm0 -16c-60.2 0 -109 48.8 -109 109c0 60.2 48.8 109 109 109c60.2 0 109 -48.8 109 -109c0 -60.2 -48.8 -109 -109 -109z"/>
</vector>
然后获取到了第二个矢量图红色部分。
这样我们就有了,变化前和变化后的图标.
把红色那部分的path内容提出来备用
我一定要说的部分:这里的 string path 是我用上面path路径匹配工具 :http://www.apkbus.com/thread-256367-2-1.html处理过的,路径一定要一一对应 ,数字内容的数值可以不一样,但是字母部分的内容一定要一样,否则他会报不匹配的错误,简单来说就是机器识别不了该怎么执行动画,他并不是很聪明,就比如 “M0,100 L3,45 L53,23”,一定对应 “M123,23 L12,43 L34,54”这种格式,“M22,35,L34,34”这样是会报错的
附带 string资源文件
res/values/strings.xml
<resources>
<string name="app_name">animate</string>
<string name="round1" translatable="false">m 109.0,27.0 h 0.0 c 45.29,0.0,82.0,36.71,82.0,82.0 v 0.0 c 0.0,45.29,-36.71,82.0,-82.0,82.0 h 0.0 c -45.29,0.0,-82.0,-36.71,-82.0,-82.0 v 0.0 c 0.0,-45.29,36.71,-82.0,82.0,-82.0 L 109.0,27.0z</string>
<string name="square1" translatable="false">m 80.0,69.0 h 60.0 c 5.52,0.0,10.0,4.48,10.0,10.0 v 60.0 c 0.0,5.52,-4.48,10.0,-10.0,10.0 h -60.0 c -5.52,0.0,-10.0,-4.48,-10.0,-10.0 v -60.0 c 0.0,-5.52,4.48,-10.0,10.0,-10.0 L 80.0,69.0z</string>
</resources>
3.2矢量动画部分
好了,我们需要的矢量资源都准备好了
1.矢量图 button_ready.xml
2.strings round1:圆形矢量
3.strings square:方形矢量
接下来准备动画了
res/anim/animator.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_longAnimTime"
android:propertyName="pathData"
android:valueFrom="@string/round1"
android:valueTo="@string/square1"
android:repeatCount="infinite"//重复次数
android:repeatMode="reverse"//表示倒序回放
android:valueType="pathType"
/>
是的你没看错这就是矢量要用到的动画,就是objectAnimator,只不过类型是path而已,其中valueFrom填的是圆形的矢量,valueTo是方形的矢量简单说就是初始状态和结束状态,我们可以通过设置矢量图 button_ready.xml中的各项参数以及接下来的动画中的参数达到不同的动画效果,具体过程请自己摸索,画多了啥都明白了。
好了第四项资源animator动画我们也有了,接下来是要把矢量原图,和动画联系起来。
划重点!!!
res/drawable/record_animator.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/button_ready"
>
<target
android:animation="@anim/animator"
android:name="c2"/>
</animated-vector>
这个xml就是把objectAnimator和矢量联系起来的重要内容 按我的理解就是把objector中的矢量动画,放在矢量图上,直接更改矢量图的内容。
首先底图是button_ready,然后我们的target指明了对button_ready文件中 path名为“ c2”的部分执行执行animator的资源动画,我就是在这里给坑到了,我把target中 "android:name="c2"这条随意命名,结果没有动画,一定注意!!!
终极实现
所有内容都搞定了,接下来我们要把动画显示出来
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ran.angsi.com.animate.MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/record_animator"
android:id="@+id/round"
/>
</LinearLayout>
MainActivity.java
package ran.angsi.com.animate;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AnimatedVectorDrawable drawable = (AnimatedVectorDrawable) ((ImageView) findViewById(R.id.round)).getDrawable();
if(drawable.isRunning()){
drawable.stop();
}else {
drawable.start();
}
}
}
在activity_main.xml中我们放了一个imageview,资源文件是record_animator
然后在activity中获取 AnimatedVectorDrawble这个矢量动画图,然后让他启动这个动画。
好了调试运行一下,结果就出来了。
这篇文章只是讲明如何实现一个动画,其他的不同效果,去看看有什么参数可以调的吧。