Orbar shapeshiftingcreatinganimations cover

Shapeshifting: Creating Delightful Icon Animations

If you enjoy talks from 360 AnDev, please support the conference via Patreon!

Animated vectors are growing in popularity, but technical expertise and learning resources for the feature remain limited within the Android community. The documentation contains surprisingly little practical information and assumes a lot of preexisting knowledge of SVGs. I’ve been disappointed to see this overlooked at conferences as well, but hope that the in-depth knowledge I’ve acquired through my own trial and error will assist other developers in creating their own awesome animations.


Introduction

This is a talk about Shapeshifting - creating delightful icon animations. My name is Or Bar, and I work at Tumblr.

History

When I graduated from university and I was trying to teach myself android, Jellybean was the new thing. I was trying to wrap my head around the fragment lifecycle, and more advanced apps and more experienced developers started introducing new navigation drawers and new elements that were not in the framework.

Next, Google Apps introduced their own navigation drawers and they had various different implementations. I wanted to know how this was done. I opened the Action Bar Drawer Toggle and I looked at the code and found that the code figured out where in the animation you are, and it drew it on the canvas. I closed the file and I figured I’ll never have the time to implement something like this.

When Timely, a clock app, came out, it had many animations. There are numbers that morphed, lines that changed size and color, bubbles that moved for no apparent reason.

I Googled around and I found this great article about number tweening. It explained how the numbers are not fonts, but rather they are past a being drawn directly to the canvas. There are control points; it was very interesting but ultimately it was very complex.

Get more development news like this

I realized that icons are more than just icons, they convey information and make the experience a good one.

Building Animations with SVG

SVG or the Scalable Vector Graphic is an image file format that’s optimized for a small file size - this results in smaller files than the equivalent png or jpeg. SVGs are also scalable, meaning that single SVG file won’t lose quality as you display it on a larger screen.

This is an SVG file - it has an SVG element with some attributes.


<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://
www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
    <title>btn_bold</title>
    <desc>Created with Sketch.</desc>
    <defs></defs>
    <g id="_Assets" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="btn_bold" fill-rule="nonzero" fill="#8F8F8F">
            <path d=“M30.156,27.644  Z” id="B"></path>
        </g>
    </g>
</svg>

Coordinate system

The SVG format uses a basic cartesian coordinate system with the top left corner as (0,0). It also supports transformations, some of them as simple as rotation scale and translation but also as complex as shearing.

The viewbox attribute, which defines the user space that will stretch to the bounds of your final container.

For example, you can define given whatever size you can define a viewbox that’s four pixels by four pixels or four by four; viewBox=”0 0 4 4”, this is how you define a grid. To actually draw, SVG has different options. One of the most important and useful ones is Path.

Path

Path represents the outline of the shape you want to draw. A path can be filled, stroked, or used to clip other paths in the same image. The ‘d’ attribute, which is also known as the Path Data, is a string of letters and numbers that represent commands for the computer to follow when drawing the shape.

The path data typically dominates the SVG file, it’s usually the longest, and therefore it’s compressed as much as possible. Commands are one letter long, white spaces and commas are omitted whenever possible.

A path also contains multiple segments which are useful when you want to compress the file even smaller. There is a fill and a stroke attribute which are used to set the colors of the shape. The fill rule is used to determine how you fill the shape.

Path Data - moveto

Instructions always start with a letter followed by zero or more parameters. Instructions can either be lower case or upper case. The difference being that uppercase instructions use absolute coordinates while lower case means relative coordinates.

Path Data - lineto

The next command is the lineto command, which is a simple instruction to draw a line.

There are two variants to this command. One for drawing horizontal lines, one for vertical, so you can stay if one character.

Path Data - curveto

The next command is the curveto, which draws a bezier curve from the current point to (x,y) using x1 y1 one as the control point at the beginning of the curve and x2 y2 as the control point at the end of the curve. The ‘S’ instruction is shorthand, and for the ‘C’, the curve instruction where the first control point is assumed to be a mirror of the second control point. There’s also ‘Q’ and ‘T’ commands that are used to draw quadratic bezier curves and an ‘A’ command is used to draw elliptical arcs.

Path Data - closepath

closepath draws a straight line from the current position to the start position of the path.

Path - Stroke

The stroke command defines the color of the path while the stroke width defines the width of the path.

Path - Fill

The fill attribute describes the color used to fill the shape that the path is describing. The fill rule describes the strategy used to fill the shape.

VectorDrawable

VectorDrawables are the Android version of the SVG format. It’s very small but powerful subset of the SVG spec. Its syntax should be familiar for Android developers.

Vectordrawables also use the coordinate system. The properties are viewportwidth and viewportheight which are equivalent to SVGs viewbox property; however, you only specify the width and height.

Coordinate system

There is width and height, which are the intrinsic width and height of the drawable and that’s used to generate pngs for supporting pre-lollipop devices.

Path

The path elements is Android’s version of the SVG path; these are very similar to SVG. Path data is the same as the ‘d’ attribute, fill color, strokecolor and strokewidth are all very self-explanatory.

VectorDrawable

This is what a vectordrawable looks like.


<vector
    android:width=“24dp”
    android:height=“24dp”
    android:viewportHeight=“24.0”
    android:viewportWidth=“24.0”>
    <path
        android:name=“circle”
        android:fillColor=“#33d4db”
        android:pathData=“M12,12m-10,0a10,10 0,1 1,20
0a10,10 0,1 1,-20 0” />
    <path
        android:name=“tick”
        android:pathData=“M6,11 l3.5,4 l8,-7”
        android:strokeColor=“#ff3b80”
        android:strokeWidth=“#1”
        />
</vector>

This draws a circle with a check mark in the center. The top-level element is the vector and it has the width, height, and the viewport width and height and then inside the vector element, we have two path elements. The path has a name attribute and that becomes useful when you want to animate the path but it’s also useful because it’s not obvious from the path data what it’s drawing. Also, the order of the path does matter for the ‘z’ index, the final ‘z’ index of the path. In this case, the check mark is drawn on top of the circle and not vice versa.

Making VectorDrawables

Android Studio has a handy tool to create vectordrawable, which allows you to pick from hundreds of material style icons.

If you get an SVG from a designer, and you import it through Android Studio, you may be left confused by why the SVG has a hole in the middle, but the vector drawable does not.

The problem is the strategy used to fill the shape. SVG is using something called the even-odd rule, and Android only started supporting that in API 24. A solution to this is to use minSdk 24, targeting 95% of the users in the room.

Some other solutions are to:

  • Convert the even-oddfill to a non-zero fill which is the rule that android supports. We draw a ray and count how many times that ray crosses a path, and if the path crosses from the left side to the right side we increase the count by one and if it crosses from the left to the right, we decrease by one.

  • Use the Support library (version 25.4 or newer) for the even-odd rule, as backporting animatedvectordrawables goes back to ice cream sandwich.

AnimatedVectorDrawable

animatedvectordrawables allow you to take vectordrawables and make them animatable. You can assign each element or each path or a group of paths a unique name and then the animatedvectordrawable can map that to objectanimators.

An animatedvectordrawable looks like a simple xml resource file that you place inside your drawable directory.


<animated-vector
    android:drawable=“@drawable/bug_droid" >

    <target
        android:name=“right_arm”
        android:animation=“@anim/wave" />
</animated-vector>

You start with an animatedvector object and you pass that your vectordrawable resource. This will be used as the start state of the animation, then you give it one or more mappings from a path or a group to an animation.

Transformations

Transformations are animations you apply to a group of one or more paths and you animate them as a unit without completely changing the shape of the path.

Suppose you start with a simple arrow that you want to flip. You can break the two parts of the arrow into two separate paths and then you can animate them separately at the same time.

In this animation, we rotate around the center point and we transform with delay back into where it’s supposed to end up.

Trimming Stroked Paths

Another very powerful property of paths is the ability to trim them before they appear on the display before they are drawn. This gives you the ability to create some nice effects so you can trim the path either at the start, at the end and you can also offset the trim position.

With a simple line, you can trim the first 20 percent, last 20 percent, and also offset the whole thing. By animating these three properties you can make nice effects, such as even recreating Material design progress bars.

Path Morphing

Path morphing is the coolest and most powerful animation that you can do with animatedvectordrawables, but it’s also one of the hardest ones to implement.

That first path and second path must have the same number of commands. The nth drawing command in the first path must have the same type as the nth drawing command in the second path for all ‘n’, where ‘n’ means that the nth drawing command.

Path Clipping

Path clipping or a path clip is a type of path that’s used to mask or restrict a region to which other paths can be drawn to. Anything that lies outside the region bounded by a clip path will not be drawn to the screen. By animating the bridge of these regions, you can create some cool effects like an eye with a slash going through it.

Resources

Next Up: New Features in Realm Java

General link arrow white

About the content

This talk was delivered live in July 2017 at 360 AnDev. The video was recorded, produced, and transcribed by Realm, and is published here with the permission of the conference organizers.

Or Bar

I’m a senior Android engineer on the mobile team at Tumblr on the mobile team. My day to day involves reimagining Tumblr’s creative tools and advanced post settings in order to incorporate the most up to date, in demand features, as well as developing projects such as our live video product and recommended tag. I have 7 years professional experience as an engineer and enjoy always chasing the latest and greatest technological trends.

4 design patterns for a RESTless mobile integration »

close