#SmallerAPK, Part 7: Image optimization, Shape and VectorDrawables

Update 1: VectorDrawableCompat has now been released!

Raster image formats like JPEG, PNG and WebP are great for some image types and sometimes even necessary, but they have two major drawbacks — their size and the fact that you need to keep them in your project in many versions for different screen densities, which compounds the problem even further. But some image types, especially icons and UI elements, can be easily recreated with a more concise representation, using XML and path information.

Shape Drawable

Available in Android from the beginning and usable regardless of platform version, this is a type of generic drawable defined in an XML file. It can only support very basic shapes, like rectangles, ovals, lines and rings, but sometimes it’s enough for simple backgrounds or decorations. Through its attributes you can also create gradients, rounded corners and outline stroke effects.

A thorough guide to shape drawables is here. You can use them whenever you would use a bitmap or other types of drawables in your layouts, e.g. in android:background or android:src.

VectorDrawables

Since API level 21 (Lollipop), Android supports a new type of drawable for representing vector graphics (perfect for icons!), called VectorDrawable.

VectorDrawables are density independent (one file will work for all screens), retain full quality when scaled and they are usually very small in size. Using VectorDrawables can have a dramatic impact for slimming down your APK.

The format is similar to SVG in that it uses the same path format, but VectorDrawables have their own XML schema. That means SVGs need to be converted before you can use them, and moreover not all SVG features are supported. You can use the Vector Asset Studio within Android Studio for the conversion.

Our Gradle Android plugin can also help if you’d like to keep your app backwards compatible. Add the following lines to your build to choose densities for which PNGs will be generated from VectorDrawables found in the drawable/ folder:

build.gradle

android {
...
defaultConfig {
//if you're using Android Gradle plugin < 2.0.0
//omit the vectorDrawables block
vectorDrawables {
generatedDensities = ["mdpi", "hdpi", "xhdpi"]
}
}
}
Note: If you don’t wish to generate PNGs, just set generatedDensities to an empty list: generatedDensities = [].

You can put the vectorDrawables block inside product flavor definitions if you’re using Multi-APK to only generate images for pre-lollipop builds.

VectorDrawableCompat

AppCompat version 23.2 now includes a backwards compatible implementation of VectorDrawables. Using this approach, with minimal changes to your layouts and code, you can forgo including generated PNGs in all versions of your app (on API 7+).

Chris Banes explains how to use VectorDrawableCompat in his post or you can check out this and other features in the new Support Library here.