Android User Interface
When you
first think about creating a user interface for an android application, you
will soon read about screen size and density. It is easy to understand, that
you should provide different picture files for a high-density tablet and a
medium-density handheld device. The part
that is hard to understand is the technical implementation. At least it was for me.
There are a
lot of information about layouts, screen sizes and densities throughout the
web. Starting point is most likely the support multiple screens site. While
this resource provides a
good overview
of the subject, it misses the most relevant point: which drawable
folders respectively which layout folders to create and where to put which
files in.
As most developers won`t read very much before creating their first sample
application, the usual starting point is shown in the picture below.
This works, if you are working just on one device. You will provide one layout and different pictures. Everything looks good until you run your application on different devices. You will notice that you have to make different layouts for handhelds and tablets, since different space is available in each category. If you do care about user experience and how your application looks like on all devices, you will start thinking about this topic again. So how to provide different layouts?
The answer
is simple. Create another layout folder and add a useful screen size
qualifier. The android documentation
provides qualifiers as small, normal, large and xlarge. While this isn`t false,
it is very outdated. As devices running API level 13 and above takes the major
market share these days, you should think in smallest width qualifier. There is
a lot of information available how to calculate this smallest width qualifier
and what density independent pixels are. Let us shorten this up here. To provide
a layout for a 10-inch tablet you have to create a folder layout-sw720dp and
put your layout.xml in there. Within this layout, you have 1280dp x 720dp to
create your user interface.
Since
7-inch tablets are very popular, we should provide another layout focusing these
devices, too. That means you also create a layout-sw600dp folder and layout
file. With your normal layout folder respectively layout-sw320dp folder you
have at least three different layouts. Furthermore, it is best practice to
provide a different layout for big screen handhelds like 5/6-inch devices. Some
resources talks about doing this by a layout-sw480dp folder but this will miss
devices like the Galaxy S3. It has 720px in smallest width and uses xhdpi
density bucket. As you might know, the density independent pixels representing
the mdpi folder. The picture size of the other folders calculate itself in
relation to this baseline folder. You might heard about the 3:4:6:8 scaling
ratio. If not, read more. That means we will need to create a layout-sw360dp
folder and layout. If you want your application to be available for devices
running API level 12 and below, you have to duplicate this layouts and create
layout-large and layout-xlarge folder. The following picture sums this up.
So we
design our layout density independent, no problem, but the pictures we have to
provide are physical files, which can`t be density independent. This leads us
back to the core questions: into which drawable folder should we put which pictures
in?
Let us
figure out what this means on something like a splash screen. On a 10-inch
device, the mdpi splash screen should be 1280x720 pixel. However, on a 4-inch
device, the mdpi splash screen should 480x320 pixel. At this point you realize,
the default drawable folder aren`t enough to handle all devices.
So what`s
the conclusion?
Provide
more drawable folder to handle them all!
To get this straight, take a look at the following picture. It gives a short overview about what`s going on in the world of android. This overview isn`t complete, most likely contains failures and is definitely outdated that moment you read this.
So what`s
the conclusion?
Provide
more drawable folder to handle them all!
You can see the size qualifier and the resource qualifier as parallel state charts. You just have to combine them. You do this by adding the size qualifier in the name of each drawable folder. For example, you create a folder named drawable-sw720dp-xhdpi to provide high-resolution pictures for the nexus 10. If you look at the picture above, you will realize that many folders are necessary to handle all devices. The following picture shows an extract of what that means.
As you can
see in the device overview picture, no matter how much combinations are
possible, there are six different resolutions packages. In reality, there are more
but you can break it down like this. A good example is the splash screen mentioned
above. Nevertheless, let's take a look at another example. If you have a button,
which is 96dp x 96dp in your sw720dp layout, it means, in your 1280x720px
picture package you have a 96x96px picture. In your 2560x1600px picture package,
you have the same button picture with 192x192px in physical size.
That means,
if you have a designer asking for physical picture sizes, you know what`s the
answer. It is still a bit more complicated since you have to create flexible
layouts using nine-patch images and resizing imageviews, but you have at least
a good starting point, now.
If there
are just six different picture size packages and dozens of drawable folder, is
it necessary to duplicate each picture multiple times? This would blow up the apk
size and that would lead to other problems. So the answer is no, you don`t have
to duplicate all pictures. You can use xml drawables to avoid this. For
example, instead of putting your button.png (192x192px) in your
drawable-sw720dp-xhdpi folder and referencing it from your layout put a
button.xml in this folder. The following xml shows an example button using
states.
<?xml
version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="@drawable/button_pressed_192" />
<item
android:state_focused="true"
android:drawable="@drawable/button_focused_192" />
<item
android:drawable="@drawable/button_192" />
</selector>
There are
plenty of different xml drawables. The android documentation tells you all you
need to know. The original png files goes into the drawable-nodpi folder and
that`s it.
Everything
works well until you try to upload this application. For some unknown reason google
play has a problem with a xml drawable icon. Again everything works fine and
every tested device uses it`s desired icon but only the upload fails. The workaround
is to duplicate the icon.png and put it in each drawable folder. Sad but the
only way to get it working.
That`s one
way to build your android user interface. There might be others. Leave a
comment and let me know what you think.