A simple, yet useful calculator for Android app designers that converts sizes between DPIs.
The most powerful tool when preparing graphics for Android is 9patch. But many people have problems understanding it, so let me try to clarify it.
9patch is essentially an image that can be stretched without distorting it. A typical example is a rounded rectangle (a typical contemporary button), where you don’t want the corners to be distorted by scaling and only want the middle parts to be stretched.
It’s not only that 9patch will get rid of the blurriness, it also locks the padding and dimensions when stretching. Notice how the non-9patch stretched image is indented and blurry.
With 9patch you define a 3×3 grid over the image. Android uses the grid to slice the image into nine parts. The four corner parts are kept, while the middle ones are scaled:
9patch is a standard PNG file that includes 1-pixel-wide transparent border. In the border, we mark the stretchable area by black pixels in the left and top lines of the border:
The image has to be saved with a
.9.png extension so Android can tell it’s a 9patch image.
Apart from marking the slices, you can also specify the padding that will be used for content (i.e., an icon or button label). The padding is adjusted when 9patch is stretched so the distances from the edges are kept the same.
Similarly to the slices, the padding is marked in the right and bottom lines of the 1-pixel-wide border by black pixels. If you omit it, Android will use the left and top markers.
With the way 9patch works, you can tell that it won’t be useful for everything. Textures or patterns are the source of most of the problems. Take a look at these examples:
The only way to handle these situations is to either not take the textures into account, or to just create a static image for every size required by the application.
Don’t forget that the 9patch resource is still just an image and that it should be also prepared for the densities.
Once you have the layout ready, you proceed to drawing. In the drawing phase, the densities come into play.
The screen density by definition is the quantity of pixels within a physical area of a screen. It’s usually referred to as dpi (dots per inch). Android splits them into four ranges:
The painful thing about densities is that we have to prepare each element for every density.
One might think that it is enough to cut images for one density and let the system take care of the scaling magic for the device. Android OS is able to resize automatically, but:
- it slows down the application, takes a lot of the system resources, drains the battery and shortly thereafter: upsets the user
- it introduces a lot of imperfections and blur, brings a lot of unwanted noise (even if it is only scaling down)
Packing all resources for all densities into one APK obviously increases the size, though fortunately Google recently announced a Multiple APK feature to its Android Market that will enable developers to create separate packages per screen size, density or resolution.
The best way to not lose your mind is to:
- draw the whole design in xhdpi, then
- cut out the parts and resize down each one separately for hdpi, mdpi and ldpi.
The densities relate to each other by a 3:4:6:8 scale ratio. So when your base is xhdpi, this is how you convert to other densities:
- ldpi = xhdpi * 0.375
- mdpi = xhdpi * 0.5
- hdpi = xhdpi * 0.75
As an example, let’s take an icon with a size of 64×64px in xhdpi:
You should be careful about what dimensions and distances you use: an example would be a 58×58px icon in xhdpi:
- 21.75px on ldpi (!)
- 29px on mdpi
- 43.5px on hdpi (!)
What is alarming are the decimals for ldpi and hdpi. With a PNG image, you cannot have a width of 43.5px. You cannot even round it: if you have 5 icons of size 43.5×43.5px side by side, it should add up to 217.5px, but if you round to 44 you end up with 220px.
When designing for xhdpi you should always use multiples of 8 for every dimension or distance. The easiest way to do this is to always use grid of 8×8 (or other multiples of 8). If you want to design for hdpi, instead of xhdpi, just use multiples of 6.
Let’s wrap it up:
- Manually prepare resources for all four densities.
- Draw the actual design for xhdpi and once you are done, cut out the parts and resize down each one separately for each density.
- You should be careful about what dimensions and distances you use. When drawing for xhdpi, always use a grid of 8x8 (or other multiples of 8).
I keep bumping into overcomplicated instructions to construct a layout based on golden ratio (such as this one). Although most of it looks cool and somewhat esoteric, it’s too much to do on a daily basis.
I use two simple formulas:
For example say your website is 960px wide:
960px × 0.618 ~= 593pxfor content column
960px × 0.382 ~= 367pxfor side column