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提取出来备用,

Paste_Image.png

上图的代码: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这个矢量动画图,然后让他启动这个动画。
好了调试运行一下,结果就出来了。

这篇文章只是讲明如何实现一个动画,其他的不同效果,去看看有什么参数可以调的吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容