AndroidAndroid 动画Android开发

Android animator-vector 矢量动画制作过程

2017-09-21  本文已影响94人  用心感受世界

起因:最近有个需求,就是拍摄时,点击拍摄图标,然后图标要变成另外一个图案。我做完功能先拿给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这个矢量动画图,然后让他启动这个动画。
好了调试运行一下,结果就出来了。

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

上一篇下一篇

猜你喜欢

热点阅读