Wednesday, 25 May 2011

Designing scalable Android apps - Fighting fragmentation with Android framework tools

In the Google I/O Google announced that there are 310 different Android devices out there. These devices come with different screen sizes, dimensions, densities, OEM skins, Android versions and even different control devices (some have touch screen, keyboard, d-pad some don't).

This variety brings new challenges to designers and developers. The apps should be designed and build the way that they work on most (if not all) devices. Fortunately the Android framework provides us a lot of useful tools to tackle the problem!

How to design for Android?
Everything starts from design. If the design isn't scalable it is very difficult to build the app to be scalable. So what should designers know about Android before starting to design?
Think about designing for web not for iOS
Web has always been scalable. There's no way of knowing what resolution user has or what is the exact pixel size of the users' browser window. iOS design, on the other hand, fully relies on absolute pixel-perfect definitions. Android is much closer to the web than iOS when it comes to design principles.

Layout Managers
Android framework provides us multiple layout managers. We can even build our own if needed. Most powerful layout manager we have is the RelativeLayout. The framework also has AbsoluteLayout class but it should never be used!

RelativeLayout is exactly what you would expect based on the name. It defines each component's location in relation of its parent or its siblings.

As an example here's a very typical layout. It has a fixed header and fixed bottom bar with buttons. The top and bottom bars ar set as fixed height and mounted to top or bottom of their parent component. The ScrollView in the middle is anchored in between of these two components. This structure makes this layout scalable.

The above layout in two different screen sizes. 

Worth noting that the latest version of Android Eclipse plugin (ADT) has an excellent layout builder that makes building RelativeLayouts even easier than before.

Android resource manager
Our next tool to fight fragmentation is Android project structure. It is possible to define more than one resource (layout, drawable, animation, values, etc) with the same name. The resources are simply placed on different folders that define when they should be used. A developer can add guidelines to the OS telling it which resource to use and when. These guidelines can be very specific or more general. The OS picks most suitable one on runtime.

For example, in the Google I/O app the developers have defined four different layouts for the app's front page.

Here's how they have done it. They have defined four different folders all containing the front page layout definition with the same file name.

Screen densities
Why does screen density matter? As pixel size (= screen density) in devices can vary if we define our components in pixels they will endup being different physical size on different devices. This matters because most of the time we're designing for touch screen devices. If a button ends up being tiny on one device and huge on an another it might be impossible for users to interact with the interface.

On the left picture of two different screen density phones side by side.
On the right screenshots of the same UIs. 

We have two tools in the Android framework to solve this problem. The first one is density independent pixels (dip / dp). A density independent pixel is a dimension definition that is automatically converted to absolute pixels by the Android OS in runtime. This conversion is always based on the screen density of the device Android is running on. Dips is a way to abstract any dimension definitions to the level where Android OS will make sure that everything is always same physical size on all devices.

In case of images we can employ the same Android resource manager we use for layouts.

9-patching is a simple but very powerful way of creating images that can be resized correctly. Better yet, they can be fully created by designer who don't have to have any Android development skills. A 9-patched image has an extra one pixel border that is used to specify which pixels should be used to stretch the image and how much padding should be used. Left and right edges define resizing and right an bottom edges the padding.

See Google's documentation for more info. They also have a handy tool for creating these images.

Advanced tricks
If the above tools are not enough we still have few more tricks we can use.

It is possible to define any variable in Android resource files (values folder). These files are handled by the same resource management mechanisms and can therefore be also used same way as layouts and drawables. This isn't limited only to dimensions. It is possible to define ints, booleans etc. the same way too.

And if everything else fails we still have one more last resort we can use. It is now possible (or at least very soon) to upload more than one APKs per one app to the Android Market. Filters can be set up to funnel certain APK to certain devices. See Google I/O Android Market presentation for more info.

Android fragmentation is an issue. But there are ways to work with it. Developers should make designers aware of these tool so they can create designs that can be implemented in scalable way. Designers don't need to know these techniques but they need to know of them. Building an app that was designed for iOS is very difficult but building an app that was designed for Android is easy.