In the previous post, I commented that the ele. me animation was done using the AnimatedVectorDrawable. This is something that was known before, but never really used. Just yesterday saw a pretty handsome vector animation (welfare at the end of the article), with interest, specially to find time to masturbate a demo to experience.

Let’s take a look at some of my demos (some SVG resources and animations collected from the web).





2017-08-17_21-26-00.gif

Not only that, these effects can be done entirely using resource files, just a simple startAnimator in Java code. Through the network resources out of these effects, to begin a system of recognition.

SVG and VectorDrawable, AnimatedVectorDrawable

SVG is relatively small in size compared to the PNG, JPG, and other bitmaps that we usually use, and records shapes in descriptive form, so it can be adapted to all sizes of resolution without distortion.

In Android, instead of using the original.svg image directly, we need to convert it to a VectorDrawable, which can be understood as an XML SVG file, the original source of vector graphics in Android.

Simply using a VectorDrawable would seem to reduce the size of apK resource files, as well as the additional CPU consumption that the SVG runtime computes (converting shape descriptions into graphics). But with AnimatedVectorDrawable, it’s a different story.

AnimatedVectorDrawable control VectorDrawable through ObjectAnimator property animation, utilizing the characteristics of vector graphics to achieve a variety of cool animation effects.





Slightly ugly diagram

Through the Demo above, I roughly divided its main animation effects into the following three.

1. Seamless switching between two graphics.





2. Draw an image based on a path.





3. Group control of different parts of the image.





These three features can be combined with other properties to achieve more complex effects.

The robot in Figure 3 actually controls the head and arms to carry out the Y-axis translation animation, while the head, hands and body belong to the same SVG picture. The first two examples in the Demo were also animated with rotated properties.

The format of the VectorDrawable

Let’s start by comparing the SVG code for a small robot vector drawing with its VectorDrawable code.

The SVG source

<? The XML version = "1.0" encoding = "utf-8"? > <! -- Generator: Adobe Illustrator 13.0.0, SVG Export plug-in. SVG Version: 6.00 Build 14948) --> <! DOCTYPE SVG PUBLIC "- / / / / W3C DTD SVG 1.1 / / EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > < SVG version = "1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="500px"  height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve"> <g Id = "max_width__x2F__height" display = "none" > < path display = = "inline" d "M499.001, 1 v498h1v1h499. 001 H0v500h500 M500.001, 0. 001 v0l500. 001, 0 z "/ > < / g > < g id =" androd "> < path the fill =" # 9 fbf3b" D = "M301.314, c1.197 l20.159 83.298-29.272-1.74, 0.899-4.024-0.666-5.104 - c - 1.563-1.074-3.805-0.543-4.993, 1.199 L294.863, 80.53 c - 13.807-5.439-29.139-8.47-45.299-8.47 - c - 16.16, 0-31.496, 3.028, 45.302, 8.47 l - 20.948-30.41 C - 1.201-1.74-3.439-2.273-5.003-1.199 - c - 1.564, 1.077, 1.861, 3.362-0.664, 5.104 l20.166, 29.272 C - 32.063, 14.916-54.548, 43.26-57.413, 76.34 h218.316 C355.861, 126.557, 333.375, 98.214, 301.314, 83.298 "/ > < path the fill =" # FFFFFF" D = "M203.956, 129.438-6.673 c, 0-12.08-5.407-12.08-12.079 c0-6.671, 5.404-12.08, 12.08 to 12.08 ,12.073 c6.668, 0, 5.407, 12.073, 12.08 C216.03, 124.03, 210.624, 129.438, 203.956, 129.438 "/ > < path the fill =" # FFFFFF" D = "M295.161, 129.438-6.668 c, 0-12.074-5.407-12.074-12.079 c0-6.673, 5.406-12.08, 12.074 to 12.08 ,12.079 c6.675, 0, 5.409, 12.079, 12.08 C307.24, 124.03, 301.834, 129.438, 295.161, 129.438 "/ > < path the fill =" # 9 fbf3b" D = "M126.383, 297.598 c0, 13.45-10.904, 24.354-24.355, 24.354 l0, 0 c - 13.45, 0-24.354-10.904-24.354-24.354 V199.09 C0-13.45, 10.904-24.354, 24.354-24.354 l0, 0 c13. 451,0,24.355, 10.904, 24.355, 24.354 V297.598 z "/ > < path the fill =" # 9 fbf3b" D = "M140.396, v177.915 c0 175.489, 10.566, 8.566, 19.133, 19.135, 19.133 h22.633 v54.744 C0, 13.451, 10.903, 24.354, 24.354, 24.354 c13.451, 0,24.355-10.903, 24.355-24.354 v - 54.744 h37.371 v54.744 C0, 13.451, 10.902, 24.354, 24.354, 24.354 s24.354-10.903, 24.354-24.354 v - 54.744 h22.633 c10.569, 0,19.137-8.562, 19.137-19.133 V175 . 489 H140.396 z "/ > < path the fill =" # 9 fbf3b" D = "M372.734, c0 297.598, 13.45, 10.903, 24.354, 24.354, 24.354 l0, 0 c13. 45,0,24.354-10.904, 24.354-24.354 V199.09 C0-13.45-10.904-24.354-24.354-24.354 l0, 0 c - 13.451, 0-24.354, 10.904-24.354, 24.354 V297.598 z "/ > < / a > g < / SVG >Copy the code

As VectorDrawable

<? The XML version = "1.0" encoding = "utf-8"? > <vector xmlns:android="http://schemas.android.com/apk/res/android" android:viewportWidth="500" android:viewportHeight="500" android:width="500px" android:height="500px"> <group android:name="android"> <group android:name="head_eyes"> <path android:name="head" android:fillColor="#9FBF3B" Android: pathData = "M301.314, c1.197 l20.159 83.298-29.272-1.74, 0.899-4.024-0.666-5.104 - c - 1.563-1.074-3.805-0.543-4.993, 1.199 L 294.863, 80.53 c - 13.807-5.439-29.139-8.47-45.299-8.47 - c - 16.16, 0-31.496, 3.028, 45.302, 8.47 l - 20.948-30.41 - c - 1.201-1.74-3.439-2. 273-5.003-1.199 - c - 1.564, 1.077-1.861, 3.362-0.664, 5.104 l20.166, c - 32.063-29.272, 14.916-54.548, 43.26-57.413, 76.34 h218.316 C355. 861126557, 333.375, 98.214, 301.314, 83.298 "/ > < path android: name =" left_eye "android: fillColor =" # FFFFFF" Android: pathData = "M203.956, 129.438-6.673 c, 0-12.08-5.407-12.08-12.079 c0-6.671, 5.404, 12.08, 12.08 12.08 c6.668, 0,12.073, 5.40 7,12.073, C216.03 12.08, 124.03, 210.624, 129.438, 203.956, 129.438 "/ > < path android: name =" right_eye" android:fillColor="#FFFFFF" Android: pathData = "M295.161, 129.438-6.668 c, 0-12.074-5.407-12.074-12.079 c0-6.673, 5.406, 12.08, 12.074 12.08 c6.675, 0,12.079, 5 . 409,12.079 C307.24 12.08, 124.03, 301.834, 129.438, 295.161, 129.438 "/ > < / group > < group android: name =" very different "> < path android:name="left_arm" android:fillColor="#9FBF3B" Android: pathData = "M126.383, 297.598 c0, 13.45-10.904, 24.354-24.355, 24.354 l0, 0 c - 13.45, 0-24.354-10.904-24.354-24.354 V199.09 c0 10.904 24.354, 13.45, 24.354-24.354 l0, 0 c13. 451,0,24.355, 10.904, 24.355, 24.354 V297.598 z "/ > < path android: name =" right_arm" android:fillColor="#9FBF3B" Android: pathData = "M372.734, c0 297.598, 13.45, 10.903, 24.354, 24.354, 24.354 l0, 0 c13. 45,0,24.354-10.904, 24.354-24.354 V199.09 c0 - 13.45-10.904-24.354-24.354-24.354 l0, 0 c - 13.451, 0-24.354, 10.904-24.354, 24.354 V297.598 z "/ > < / group > < path android:name="body" android:fillColor="#9FBF3B" Android: pathData = "M140.396, v177.915 c0 175.489, 10.566, 8.566, 19.133, 19.135, 19.133 h22.633 v54.744 c0, 13.451, 10.903, 24.354, 24.3 54,24.354 c13.451, 0,24.355-10.903, 24.355-24.354 v - 54.744 h37.371 v54.744 c0, 13.451, 10.902, 24.354, 24.354, 24.354 s24.354-10.903, 24.354-24.354 v - 54.744 h22.633 c10.569, 0,19.137-8.562, 19.137-19.133 V175.489 H140.396 z "/ > < / group > < / vector >Copy the code

We can clearly see some common labels. Similar to width, height, g and group, path, etc. SVG source code is more tags, we do not need to care about. The most important part of SVG is its path-path.

As mentioned earlier, SVG records graphics by describing shapes, known as paths. If you’ve ever played with a brush, you go from one point to another. The width and height indicate the size of the canvas, and the coordinates of our path should be within the corresponding width and height, beyond which we cannot see it.

Usually Path is a complete Path. In the robot, there are arms, body and other different parts, so there are multiple paths to describe. The VectorDrawable names and groups the parts so that it looks clear. Usually simple shapes can be described using a Path.

So, with a Path, we can convert an SVG image into an Android available VectorDrawable.

Get the VectorDrawable moving

Take the first effect in the demo for example.

Let’s take a look at its XML components.

<ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:onClick="btnClick"
        android:src="@drawable/animated_play_pause"
        android:background="@color/colorPrimary"
        android:layout_marginTop="20dp"
        />
Copy the code

The image resource referenced by ImageView is animated_play_pause

<? The XML version = "1.0" encoding = "utf-8"? > <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vector_play"> <! <target Android :animation="@animator/animator_play_pause" Android :name="play"/> <! <target android:animation="@animator/animator_rotate" Android :name="playgroup"/> </animated-vector>Copy the code

This is the legendary AnimatedVectorDrawablele. In this XML, we first declare a default VectorDrawable object, Vector_play, with the drawable tag, which is our vector play key.

There are two targets defined with two parameters, animation and name. The former defines the animation effect to be used, and the latter is the target object for the animation effect. This name must be the same as the name declared by the path and group of the VectorDrawable object, or an error will be reported if the object is not found when the animation starts.

Two animation

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" Android :valueType="pathType" android:propertyName="pathData" android:valueFrom="M 3,2 L7,5 L7,5 L3,5z M 3,8 L7,5 L7,5 L7 L3,5z" android:valueTo="M 2,2 L8, 2 L8,4 L2,4z M 2,8 L8,8 L8,6 L2,6z"Copy the code
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="rotation"
    android:valueType="floatType"
    android:valueFrom="0"
    android:valueTo="-90"/>
Copy the code

The first is the animation that switches from play to pause, just like using normal property animation, except valueType and propertyName are pathType and pathData respectively, indicating that the animation is for path changes. Yes, the effect of vector animation is simply to switch from one shape path to another. The ValueFrom argument is actually the play key path argument, valueTo is the pause key path.

We won’t talk more about rotation animations, but one thing to note is that the two names in target are different. Where play is the name of the path and palyGroup is the name of the group where the path belongs.

<? The XML version = "1.0" encoding = "utf-8"? > <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="100dp" android:height="100dp" android:viewportHeight="10" android:viewportWidth="10"> <group android:name="playgroup" android:pivotX="5" Android :pivotY="5"> <path android:name="play" android:fillColor="# FFF "android:pathData="M 3, 2l 7, 5l7,5 L3,5z M 3,8 L7,5 L7,5 L3,5z"/> </group> </vector>Copy the code

Instead of animating the Path directly with properties such as rotation and pan, target the group that wraps the Path, otherwise the following error will occur. FullPath unsupported animation properties.





Here we have a shape change plus rotation AnimatedVectorDrawable. Click to trigger the animation, as shown in Java:

public void btnClick(View view) { ImageView imageView = (ImageView) view; Drawable drawable = imageView.getDrawable(); if (drawable instanceof Animatable) { ((Animatable) drawable).start(); }}Copy the code

The attached

Added 1 Path drawing

Corresponding to the transform animation is an animation that draws the path. In fact, it’s pretty simple. It changes the corresponding parameter to trimPathEnd, and the value change is 0 to 1, which means it’s completely drawn. These are some basic applications, you can download my Demo at the end of this article to get the full SVG resources, try it yourself.

<? The XML version = "1.0" encoding = "utf-8"? > <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:propertyName="trimPathEnd" android:valueFrom="0" android:valueTo="1" android:duration="5000" android:valueType="floatType" android:interpolator="@android:interpolator/linear"/>Copy the code

Add 2 animator-vector for multiple animator-vector sets.

When we use the animator_vector, there are only two states: from to, both for drawing and for shape switching. After the switch, if we want to switch to a third path, or to switch back, then we need to use animator-selector.

Similar to selectors, different animator-vectors can be executed using different states to switch back and forth between different paths. As in the demo love and Twitter toggle back and forth effect.





Searchbar in demo is combined with trimPath effect.







Added 3 Path syntax

There are many paths listed in the code above, and while we don’t need to manually calculate the Path of the vector graph, we still need to clean up the meaning.

M: move to Draw the starting point (Mx, y) L: line to draw a straight line to a point (Lx, y) H: horizontal line (Hx) V: vertical line (Vy) Z: close Close The first and last parameters are not specified C: Cubic Bezier curve (X1, y1, X2, y2) Q: Quatratic Bezier quadratic Bezier curve (X1, y1, X2, y2, x3, y3) A: Ellipse arc

Each command has a case format: uppercase indicates absolute coordinates and lowercase indicates relative coordinates. Parameters are separated by Spaces or commas. Interested in reading their own official documents, playing dead people pay for their lives series.

Supplement 4 on coordinate matching

In fact, not any two SVGS Can be switched seamlessly, and if you want to switch between two graphics properly, you will usually get the error of “Can’t morph from x to Y” when you start looking for two graphics to switch. So the format of the two paths must match.





image.png

Often the paths generated by software are very strange, and if the paths are complex they are very difficult to change. VectAlign is an open source project on Github that computes the paths of two SVGS so that they can switch seamlessly.





Added 5 a great vector animation libraryRichPath

It works great, controlling paths and properties freely in code, much more maneuverable than pure resource files, well, much cooler than mine…





Forgive me for stealing a map

Supplement 6 on welfare at the end of the article

This article Demo complete project address

Self-made vector animation practice how to get rid of UI?? . here

References and some SVG source materials

VectorDrawable series of short books with good advanced Animation at the end of the benefits of my cool effects of anime. Js: Implementing an SVG Morphing Animation