Recently a call for help caught my eye; asking how to implement a fancy ‘getting location’ animation on Android:
I immediately thought this was a prime candidate for an
AnimatedVectorDrawable (AVD hereafter) so set out to demonstrate one way to implement this. Some people asked how I did this… so here’s a breakdown.
Looking at the composition, this is made up of three types of animation:
- The pin moves & changes shape to make it jump; AVD supports this by animating the actual shape of a path, known as path morphing.
- The dots move leftward, this will be a simple translate.
- The dots fade in/out as the enter/exit the scene.
Unfortunately I didn’t have access to the source artwork, just the GIF on dribbble… hopefully you won’t have to do this in your animations!
I opened the GIF in Photoshop which provides a timeline view of the frames of the animation. I stepped through this and saved copies of frames where the pin was at extremes of movement i.e. about to change direction or change shape significantly. These ‘poses’ will be the shapes that the pin will morph between. In total there were 5 major poses.
I pasted each of these into Sketch (my preferred vector drawing tool) and traced out the pin in each of the poses.
Some tools can automatically trace raster images and produce vector paths for you. Knowing that I wanted to perform a path morph animation however, meant that I needed ‘compatible paths’; that is each path needs to have the same number and type of points. As such by drawing the pin with a simple shape (made up of 8 points, each with 2 control points) and manually altering it to form each pose I could be sure that we can later animate between the shapes.
I then exported each frame as individual SVG files. Now SVG is a vast spec and Android’s
VectorDrawable only supports a subset of it. It’s also helpful to remember that they need to be parsed and rendered on a constrained mobile device; therefore I always try to simplify my SVGs. To do this, I ran them through SVGO (using SVGOMG by Jake Archibald) setting the precision to 1 decimal place.
Now that we have the paths of each pose of the pin, it’s time to make them move! To do this I turned to the awesome Icon Animator by Roman Nurik. This is a web-based IDE for creating
AnimatedVectorDrawables. I dropped in the first SVG and then clicked on the stopwatch icon next to the pin layer and added a new
pathData animation. This produces an inspector panel where I could insert the path of the pin from the next frame into the
toValue. I repeated this 4 more times to make our animation (where the last step animates from the final pose, back to the initial one).
For the timing values I referred back to the original GIF where each frame lasted 30ms so if there was 4 frames between poses, use a duration of 120ms etc. I chose to just use standard material interpolators, but in reality this could benefit from fine tuning.
For the dots which move along we can perform a simple translation. Looking at the source composition, every third dot is larger and red; how to implement this in a nice loop? While you could implement this with just 3 dots and animate each individually; I decided to include 5 dots where the rightmost dots extend beyond the viewport:
Doing this allows us to animate the entire group of dots leftward all together, once the 4th dot reaches the initial location of the 1st dot, we instantaneously reset the translation, jumping it back to it’s starting point. Neat!
Coming and Going
We want the dots to fade in as they enter and fade out as they leave, this is a simple animation of the
fillAlpha, I leave that up to you to see how it’s achieved!
Loop the Loop
Now to make this into a complete looping animation there are a few things to consider. The dot animation has triple the duration of the pin jumping. I considered breaking them into 2 separate AVDs and layering them… but decided that repeating the jump 3 times was simpler!
I hit the magical export button in Icon Animator which gave me the AVD definition, ready to drop into my project. The tool however is still in ‘preview’ so I made a few tweaks to it to clean up the output, namely removing any redundant attributes and factoring out any repeated values (like the different pin paths and some colors) to a resources file to make them more maintainable.
Actually making the full AVD loop was trickier than i’d envisaged. Apparently
repeatMode on animations
sets are ignored 😡 (bugs have been filed). I worked around this by listening for the end of the animation and starting it again. Unfortunately callbacks were only added in API23 but you could achieve the same effect via
Hopefully this post has shown you that
AnimatedVectorDrawable is very powerful and that you can create rich animations relatively easily. I also hope that sharing my workflow helps to demystify the process and maybe inspires you to create your own. Let me know if you do!