Building a mobile application is generally fun. New technologies, things to think about like memory constraints and threads… However, one thing that bugs me is a clear indication on how to build pixel perfect apps.
IOS has a limited number of resolutions, plus their strategy is “normal size” or “retina display size”, which is 2x of the normal size. Therefore, creating assets (bitmaps) is feasible. Android has, unfortunately, a complex relationship between densities, sizes and pixels.
Android UI Guidelines
First, we have to recognise there are a large number of different devices out there, with different screen sizes. Then, there’s the pixel density, measured in dpi (dots per inch). Then, there’s the screen resolution, measured in pixels (px) (this one is the dimension which most are familiar with). However, the guidelines say this about the resolution:
When adding support for multiple screens, applications do not work directly with resolution; applications should be concerned only with screen size and density, as specified by the generalized size and density groups.
Soo.. where does this leave us? Well, this leaves us in the land of density-independent pixel (dip). This is why you see dimensions in dip in all applications. The question then becomes:
How on earth do I do my graphics to be pixel perfect, but in dip?
Well, the answer is simple: By creating multiple versions of your asset. How many? the guidelines define a bunch of densities ( ldpi , mdpi , tvdpi , hdpi , xhdpi , xxhdpi , xxxhdpi ). So, worst case scenario, you’d need to create one version for every resolution. Fortunately, android can degrade gracefully, in the sense that if you don’t have the preferred resolution it will get another one and scale it accordingly. …but I digress.
The question still remains: What’s a dp? Photoshop works in e.g. pixels and if you want to create a nice template/base, you’ll work with pixels too.
DP in Pixels
More experienced developers and designers went about defining a relationship of dip’s and then a correspondence from dip in px. mdpi is the reference density. That is, 1 px on an mdpi display is equal to 1 dip. The ratio for asset scaling is:
Google recommends that you develop the hdpi graphics. You can add more densities (in drawables/) if you deploy on more devices (e.g. add the “tv” option if you develop an app for e.g. Google TV). Some users add the extra densities for better clarity (e.g. more complex graphics for higher resolutions)
What this means is if you’re doing a 48dip image and plan to support up to xhdpi resolution, you should start with a 96px image (144px if you want native assets for xxhdpi) and make the following images for the densities:
|Icon size||36 x 36||48 x 48||64 x 64||72 x 72||96 x 96||144 x 144||192 x 192|
And these should display at roughly the same size on any device, provided you’ve placed these in density-specific folders (e.g. drawable-xhdpi, drawable-hdpi, etc.)
For reference, example pixel densities for these are:
I wrote “example” because e.g. xxhdpi pixels have different dpi’s, depending on the actual screen size (or, at lest that’s my interpretation).
A little experiment: If you find this post and ad below useful, please check the ad out :-)