XML Drawables for Android Developers

It’s good to know what you can do in xml to draw something on the UI.
I recently noticed that I and some colleagues tend to overcomplicate simple tasks, because we don’t really know the built-in possibilities. Sometimes the design requires a not too complex, but not so simple (e.g. a shape) drawing on the UI. The first thing we think of is creating a custom View, override the onDraw method, and et voilá. But in most of the cases there is a much simpler solution with well defined drawables.
There are a bunch of drawable types, you can check them on this official developer link. Most of them are about how to combine drawables into one. Typically the layer-list is, as the name suggests: layer drawables over each other or over the state-lists, with which you can apply different drawables for different states of UI elements (mainly for buttons). We are going to dig into them a little bit, focused on the result of them.

XML Bitmap

Good to know, that bitmaps (icons) can be “modified” in xml format. You just set the icon as src, and add extra attributes to modify it. You can set the tilemode, gravity or filter (smoothen if the original image is shrank or stretched) or from other aspects, set the tint of the icon(!), to check the most important ones. The last thing about it is that you can use XML Bitmap instead of drawable attributes in other drawables. This way you can keep your code clean from drawable manipulations.

ShapeDrawables

You can create simple drawables from base elements, like rectangle, oval, line and ring.

xml drawables android rectangle example

android xml drawables oval example

xml drawables android ring example

xml drawables android line example

Because this line shape implementation is quite boring, I added a little rotation too to demonstrate how easy it is to manipulate drawables.

TransitionDrawables

Changing icons on the same view is not a rare occasion. You can change it easily by code, but it will flash while changing, therefore you should write an animation for a nice effect.

Instead you can define a TransitionDrawable, add the states, and change it programmatically to get a nice crossfade effect.

The result is:

android xml drawables transitiondrawable example

LayerDrawables

LayerDrawable can hold an array of drawables similar to FrameLayout, all the new layers are on top of the previous one. You can also position the layer inside the parent and give them gravity too.

android xml drawables crossfade before

It is not complicated to put items together this way. You can use other xml drawables, vector drawables or pngs. If you use pngs, then you can wrap them into bitmap tags, to apply more properties (for exapmle tint color).

The result is:

android xml drawable crossfade

LevelListDrawable

LevelListDrawable usage is almost similar to plurals. You can combine several drawables into one, with maxLevel and/or minLevel values. You can set the level programmatically with setLevel of the drawable, that changes to the right drawable.

With a little trick you can add an enter and exit duration that causes it to fade instead of a flash.

Clip Drawable

This is quite similar to the level list drawable above, but you can set only one drawable you want to clip (and you have to cast it to ClipDrawable). You can set the level of this drawable between 0 and 10,000, where 0 is the default value, therefore it won’t be visible until you set it to a bigger value.

StateListDrawables

I hope this is a widely known drawable type – used mainly for buttons or any relatives. This is also a list of drawables, but with additional states.

You have several different states to choose from and you can find them here: https://developer.android.com/reference/android/graphics/drawable/StateListDrawable.html

The most commonly used states are: pressed, checked/selected, enabled, and of course the default drawable without a state as a fallback at the end. You can set one drawable to a Button’s background and change its state to achieve the new look.

Previously, this was the way developers showed the users that interaction happened. Nowadays, you have more options to use. There is an easy thing elevation (achievable with, for example, statelistanimator), you can change on tap and release, and another one is the ripple effect (see below).

There are also some neat properties, as you can see in the example, the enter/exit fade duration. These add a pretty crossfade instead of a flash.

RippleDrawable

This so-called ripple effect came in with Lollipop, but there are several third paty libraries that hels to backport it on earlier android versions too.

Creating the ripple effect is quite easy, but you can modify the area where the ripple will occur with a mask (an item tag with the “@android:id/mask” as id). You can use any kind of drawable for the masking. This way you can create a rectangle shaped button, with an invisible anyshape mask, where the ripple takes effect.

On devices with os at least Lollipop, you get this nice effect built-in. You can add this effect on any other view types if they are clickable. It can be done with something like the above, or with a built-in drawable(“?attr/selectableItemBackground” as backround). This built-in solution uses the default android:colorControlHighlight property of your style; you can set it as you wish.

NinePatch

When you use pngs as drawables, you have to take care of the scaling issues. For example, if you have a rectangle-shaped png, but you would like to use it for a screenwide buttons’ background, it will be stretched a lot. This is where 9-patch comes in to aid you.

You can define pixel columns and/or rows that can be stretched if necessary. Previously, you had to use third party tools, to create and edit nine patch files, but now Android Studio has a built-in tool, to generate 9-patch file from png, and to edit them (right click on png file and Create 9-Patch file…).

This tool has a preview too: you can check instantly how your nine patch will look like in different scenarios.

Vector Drawable

There is a trend nowdays, to leave the oldtimer pngs as icons behind and use vector drawables instead.

Vector Drawables are fully supported from Lollipop and up, but now they are supported on older devices too, with some limitations however. For these older devices pngs are generated at build time, in several densities. Hint: you cannot animate the image modifications, called path morphing.

Otherwise there is one really big advantage of using vector drawables, rather than pngs. Vector drawables can be scaled to any size without degradation in quality, therefore it is enough to use only one file, not one for each screen density.

You can import (New Vector asset) several built-in material icons into your project.

Here is the default accessibility icon:

xml drawable vectordrawable

As you can see, the color is right there directly, therefore it is really easy to manipulate it. The pathData is another thing, but you can play around with it, to get the wind of it.

Another good point for vector drawables: they can be animated. Animated in a really fancy way, actually. You can add the name property to a path, or you can add a named parent group tag too (with additional properties, for example pivot info), and apply animation on the named items like in an original Android Developer example: https://developer.android.com/reference/android/graphics/drawable/AnimatedVectorDrawable.html

Here are some other interesting videos: https://www.youtube.com/watch?v=wlFVIIstKmA

Summary

This work is just an overview of the possibilities, but I hope it helped you if you are searching for some new solutions.

During the research work I came across several solutions I’ve never heard about before, and I got quite enthusiastic about vector drawables, and even moreso about their animations. Luckily our projects are quite diverse so I get plenty of opportunities to play around with these tools. If I left out your favorite xml drawable resource, please share in the comments!

Otherwise, you might be interested in my post on the best Android crash report tools.

Gergely Szőke

Gergely Szőke

Having a baby means, in order to keep up, you have far less time for sleeping, but it's definitely worth it.