Android 矢量图(VectorDrawable)及动画(AnimatedVectorDrawable)

VectorDrawable

矢量图形的优点在这里就不再多介绍了,并且矢量图形在安卓的Lollipop中已经实现了,相关的类就是VectorDrawable。
下面先通过一个小例子来看一下VectorDrawable的运用
layout: main.xml

<ImageView  xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/heart"/>

drawable: heart.xml

<vector  xmlns:android="http://schemas.android.com/apk/res/android" android:height="250dp" android:width="250dp" android:viewportHeight="32" android:viewportWidth="32" >
    <path  android:name="heart" android:fillColor="#e91e63" android:pathData="M20.5,9.5 c-1.955,0,-3.83,1.268,-4.5,3 c-0.67,-1.732,-2.547,-3,-4.5,-3 C8.957,9.5,7,11.432,7,14 c0,3.53,3.793,6.257,9,11.5 c5.207,-5.242,9,-7.97,9,-11.5 C25,11.432,23.043,9.5,20.5,9.5z"/>
</vector>

效果:
heart
是不是感到十分神奇,一个心型图案就这样表现出来了,在这个过程中没有使用任何png图片。
其中这里最让人不解的是pathData里面的那些数字,正是这些数字让这个drawable呈现出心形。pathData指的是绘制一个图形所需要的路径信息,那么问题来了,我怎么知道该如何绘制呢?
w3c的文档中详细讲解了绘制的规则:http://www.w3.org/TR/SVG11/paths.html#PathData 。其实在svg格式的图像中也是使用这种规则,而且在安卓中android.graphics.Path Api对路径的定义也差不多是这种规则。
虽然有对path 规则的绘制教程,但是要创造出现有安卓中各种图标的效果是很难的,要让VectorDrawable有实际价值,肯定不能让开发者去想办法实现这些图形的绘制,而是原本就有很多现成的图像可用,8000个已分类好的扁平化图标(PNG/SVG/WEBFONT)http://www.shejidaren.com/8000-flat-icons.html, 从网上的搜索结果来看svg的图标是大有人在。

SVG Path Data

下面对一些常用的命令来做一下介绍:
1. M: move to 移动绘制点
2. L:line to 直线
3. Z:close 闭合
4. C:cubic bezier 三次贝塞尔曲线
5. Q:quatratic bezier 二次贝塞尔曲线
6. A:ellipse 圆弧
参数:
7. M (x y) 移动到x,y
8. L (x y) 直线连到x,y,还有简化命令H(x) 水平连接、V(y)垂直连接
9. Z,没有参数,连接起点和终点
10. C(x1 y1 x2 y2 x y),控制点x1,y1 x2,y2,终点x,y
11. Q(x1 y1 x y),控制点x1,y1,终点x,y
12. A(rx ry x-axis-rotation large-arc-flag sweep-flag x y)
rx ry 椭圆半径
x-axis-rotation x轴旋转角度
large-arc-flag 为0时表示取小弧度,1时取大弧度
sweep-flag 0取逆时针方向,1取顺时针方向

AnimatedVectorDrawable

VectorDrawable也是可以做各种各样的动画的,AnimatedVectorDrawable类可以去创建一个矢量资源的动画。
你通常在三个XML文件中定义矢量资源的动画载体:
1. 元素的矢量资源动画,在res/drawable/(文件夹)
2. 元素的矢量资源,在res/drawable/(文件夹)
3. 元素的一个或多个对象动画器,在res/anim/(文件夹)
矢量资源动画能创建和元素属性的动画。元素定义了一组路径或子组,并且元素定义了要被绘制的路径。
当你想要创建动画时去定义矢量资源,使用android:name属性分配一个唯一的名字给组和路径,这样你可以从你的动画定义中查询到它们。
下面来看两个例子,这两个例子可以从https://github.com/chiuki/animated-vector-drawable中得到。

Clock

MainActivity.java

public class MainActivity extends Activity {
    private ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_clock);

        imageView = (ImageView) findViewById(R.id.image);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animate();
            }
        });
    }

    private void animate() {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof Animatable) {
            ((Animatable) drawable).start();
        }
    }
}

布局文件:就一个ImageView,使用矢量动画图像作为source。
layout: activity_clock.xml

<ImageView  xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/nine_to_five"/>

定义一组矢量图形的动画
drawable:nine_to_five.xml

<animated-vector  xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/clock" >
  <target  android:name="hours" android:animation="@anim/hours_rotation" />
  <target  android:name="minutes" android:animation="@anim/minutes_rotation" />
</animated-vector>

矢量图形
drawable:clock.xml

<vector  xmlns:android="http://schemas.android.com/apk/res/android" android:height="200dp" android:width="200dp" android:viewportHeight="100" android:viewportWidth="100" >
  <group  android:name="minutes" android:pivotX="50" android:pivotY="50" android:rotation="0">
    <path  android:strokeColor="@android:color/holo_green_dark" android:strokeWidth="4" android:strokeLineCap="round" android:pathData="M 50,50 L 50,12"/>
  </group>
  <group  android:name="hours" android:pivotX="50" android:pivotY="50" android:rotation="0">
    <path  android:strokeColor="@android:color/holo_blue_dark" android:strokeWidth="4" android:strokeLineCap="round" android:pathData="M 50,50 L 24,50"/>
  </group>
  <path  android:strokeColor="@android:color/holo_red_dark" android:strokeWidth="4" android:pathData="M 50,50 m -48,0 a 48,48 0 1,0 96,0 a 48,48 0 1,0 -96,0"/>
</vector>

动画
anim:hours_rotation.xml

<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="8000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="240"
    android:interpolator="@android:anim/linear_interpolator"/>

anim:minutes_rotation.xml
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360"
    android:repeatCount="7"
    android:interpolator="@android:anim/linear_interpolator"/>

注意这里的android:propertyName使用rotation,当然在下个例子中我们用的是android:propertyName=”pathData”,可以对比一下。

Face:

layout: activity_face.xml

<ImageView  xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/smiling_face"/>

drawable:smiling_face.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/face" >
  <target  android:name="mouth" android:animation="@anim/smile" />
</animated-vector>

drawable:face.xml

<vector  xmlns:android="http://schemas.android.com/apk/res/android" android:height="200dp" android:width="200dp" android:viewportHeight="100" android:viewportWidth="100" >
  <path  android:fillColor="#ff0" android:pathData="M 50,50 m -48,0 a 48,48 0 1,0 96,0 a 48,48 0 1,0 -96,0"/>
  <path  android:fillColor="@android:color/black" android:pathData="M 35,40 m -7,0 a 7,7 0 1,0 14,0 a 7,7 0 1,0 -14,0"/>
  <path  android:fillColor="@android:color/black" android:pathData="M 65,40 m -7,0 a 7,7 0 1,0 14,0 a 7,7 0 1,0 -14,0"/>
  <path  android:name="mouth" android:strokeColor="@android:color/black" android:strokeWidth="4" android:strokeLineCap="round" android:pathData="M 30,75 Q 50,55 70,75"/>
</vector>

anim:smile.xml

<objectAnimator  xmlns:android="http://schemas.android.com/apk/res/android" android:duration="3000" android:propertyName="pathData" android:valueFrom="M 30,75 Q 50,55 70,75" android:valueTo="M 30,65 Q 50,85 70,65" android:valueType="pathType" android:interpolator="@android:anim/accelerate_interpolator"/>

注意这里用的是属性是android:propertyName=”pathData”

Reference

http://mobile.51cto.com/news-478709.htm
http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0123/2346.html
http://blog.csdn.net/xu_fu/article/details/44004841

http://www.w3.org/TR/SVG11/paths.html#PathData
https://github.com/chiuki/animated-vector-drawable
https://gist.github.com/nickbutcher/b3962f0d14913e9746f2

你可能感兴趣的:(android,动画,矢量图)