App Development

Muzei-esque Animated SVG Drawing for Android

WillowTree default article featured image

A while back, the singular Roman Nurik released an open source live wallpaper called Muzei, which showcases famous works of art on your Android home screen and provides an API to integrate other image sources. Many aspects of this app immediately struck my fancy, but the first was the sleek and fluid logo shown when a user opens up the app.

Embedded content: https://www.youtube.com/embed/_V07MhtKX8E?rel=0

Thanks to Muzei being open source, anyone can see how the drawing of this logo is accomplished. The util package contains most of the magic, with AnimatedMuzeiLogoFragment, AnimatedMuzeiLogoView, LogoPaths, MathUtil, and SvgPathParser being our classes of interest. Here’s a brief description of what these classes do:

  • AnimatedMuzeiLogoView an Android View class that draws SVG paths with various options for strokes, fills, and durations
  • SvgPathParser a parsing utility that convert SVG paths to Android Path classes, enabling them to be drawn to a Canvas
  • MathUtil a utility that makes certain calculations easier
  • AnimatedMuzeiLogoFragment a Fragment that encapsulates an AnimatedMuzeiLogoView and a subtitle view, handling animations and callbacks for drawing and filling the logo
  • LogoPaths a Java file that defines SVG paths as static Strings

AnimatedMuzeiLogoView is declared in res/values/layout/animated_logo_fragment.xml. Here you can see that it is given a static width and height, and the subtitle view is placed next to it for animating. AnimatedMuzeiLogoFragment is then declared in two places: about_include_content.xml, which is shown in the About screen, and muzei_include_intro.xml, which is shown on app launch.

We’ve taken the first three classes and added some functionality. Namely, the AnimatedMuzeiLogoView is now OAK’s AnimatedSvgView, which can scale and resize itself and allows for separate ARGB paints per glyph. AnimatedMuzeiLogoFragment and LogoPaths are left to the developer to implement. The Fragment class is not necessary to use the view and simply serves to better encapsulate the animation logic. The LogoPaths class is required but should be defined by you to implement your own SVG paths.

Using OAK’s AnimatedSvgView Now that we have a bit of context on how Muzei interacts with the SVG format, let’s try using OAK’s tweaked version of that to create a nice animated path. We’ll use the standard Android logo (Bugdroid) as an example. Note: the resources I created during this project are all in the project_resources directory of the Git repo, available here.

The first step is to take each “glyph” of Bugdroid and turn it into a text SVG path. Following the instructions here, I created a path in GIMP for each of the four sections of Bugdroid: its head, body, left arm, and right arm. One very important thing to note is that I did not use the “Invert” option when creating the paths. I then exported each of those paths and copied in the text values of the SVG path to the AndroidLogoPaths.java file you find in the app itself. That String array, ANDROID_GLYPHS, contains four Strings, each corresponding to one of Bugdroid’s sections. Note that the order matters, in that you can optionally delay the animation of each glyph, for some nice effects. Also note that copying and pasting this in is a bit tedious. I did a replace all on /n and some of the whitespace characters to make things more readable.

After you’ve exported and imported your paths, you’ll need to add an AnimatedSvgView to your layout. OAK’s AnimatedSvgView expands on Muzei’s AnimatedMuzeiLogoView in one key way: it uses aspect ratios to lay itself out responsively, and can thus scale to fit screens or content as you see fit. To ensure that the view scales properly, assign an oakSvgImageSizeX and oakSvgImageSizeY, which should correspond to your original image’s sizing. Then use wrap_content for either your layout_width or layout_height. You should also declare (as attributes) oakSvgTraceTime, oakSvgTraceTimePerGlyph, oakSvgFillStart, and oakSvgFillTime. These are values in milliseconds.

Finally, take a look at your Activity. I prefer to create a Handler to delay drawing of the path just slightly. Apart from that, it’s a matter of programmatically setting the glyphs used by the view, setting the ARGB paints to fill the glyphs with, and then setting the trace and residue colors for the glyphs.

Embedded content: https://www.youtube.com/embed/3mq1Ezwxtus?rel=0

One Step Further Take a look at WillowTreeLogoActivity to see how to use the callbacks of AnimatedSvgView to animate other views like a subtitle. Because this fancy SVG drawing class is just a View at heart, it can be animated as well, so feel free to experiment with animating the views both during the drawing and after!

One more thing: if you’re interested in doing stuff like this professionally, drop me a line. WillowTree is always looking for talented software engineers! Embedded content: https://www.youtube.com/embed/6-AKbJ3xMtI?rel=0

Quickstart-Guide-to-Kotlin-Multiplatform

A Quick Start Guide to Kotlin Multiplatform

Kotlin Multiplatform, though still experimental, is a great up-and-coming solution...

Read the article