Designing apps for Android can be incredibly difficult at times. The multitude of screen sizes and pixel densities between devices means that layouts must be designed to dynamically flow, and image resources must scale correctly. When I first started creating Android applications, the UI was one of the most difficult aspects to master. And being a terrible graphic designer by nature, I was lucky enough to be able to work with several talented designers who helped me figure out how to style apps quickly and target the majority of screen configurations out there.
First, you must understand how Android has allowed developers to better tackle the issue of developing for various screen sizes and pixel densities. It has become quite a bit more complicated with the proliferation of Android tablets on the market, so for the purposes of this post, I’ll keep it simple and try to only address my experience when developing apps for the phone form factor.
Most phones fall into the ldpi (low), mdpi (medium), and hdpi (high) categories. If you have ever created a new Android application in Eclipse, you have likely noticed a “drawable-hdpi,” “drawable-mdpi,” and “drawable-ldpi” folder created by default in the “res” directory of your new project. The last time I checked, low-density devices made up only 3-5% of devices on the market. Because of that, I decided to only target medium and high-density devices in my own development.
Designing comps and image resources
My first piece of advice is to have the designer design all comps for your application in two sizes: 320×480 and 480×800. The first will be for mdpi devices and the latter for hdpi.
Then, when the comps get sliced up into their individual image resources, make sure you place the hdpi resources in the “drawable-hdpi” folder and the mdpi resources in the “drawable-mdpi” folder.
Also, have the designer mark up any heights or widths that must be translated to your XML layouts in the mdpi comps. Android has a measure of unit called “dip” or density independent pixels that should be used in styling your layouts, and all dip measurements use mdpi as the baseline, which is why you’d want to assign them based upon the 320×480 layout.
Designing/styling your XML layouts
Layouts must be designed to flow appropriately between various screen sizes. If you have any web development background, this will probably be a bit easier for you on a conceptual level. However, if this is your first time designing dynamic UI layouts, this could be one of your biggest struggles to get right. And it’s certainly much different than the pixel-perfect layouts in iOS.
When I attempt to convert a designer’s comps to an actual layout, the first thing I do is to try and visualize the different UI elements and how they all fit together. In order to do this, you need to have a strong grasp on the different options available to you in Android. I have found this reference incredibly helpful in the past, so it’s probably a good idea to study that page and view all the examples if you haven’t already.
I tend to use LinearLayouts and RelativeLayouts the most and occasionally use TableLayouts. However, I tend to use ListViews more than TableLayouts since I find them easier to dynamically bind data to and assign generic onClick handlers to the rows. RelativeLayouts are incredibly useful when trying to place UI elements in specific locations relative to other elements.
Assigning dynamic heights and widths
In lieu of hard-coding heights and widths into your UI elements, Android provides several identifies that can be used instead:
• match_parent (same as fill_parent after API level eight)
The first two should be fairly self-explanatory, and the last one means that you allow the UI element to take up as much space as is needed when it is scaled. This ties back in to the earlier topic of developing image resources. If you have followed my suggestions, then when you create your layouts and define your ImageViews, you should be able specify “wrap_content” for both height and width of each image, and they will display correctly on both mdpi and hdpi devices with no scaling necessary.
If the design demands that a height or width must be defined, then as mentioned earlier, use “dip” as the unit and enter values based upon the ones from the mdpi comp. If you do this correctly, your layouts should scale perfectly between various screen sizes, and you won’t have to define a separate xml file for mdpi and hdpi.
LinearLayouts support what is called layout_weight in Android. Layout weights are, in a nutshell, a way for you to assign importance to UI elements in regards to what portion of leftover, unused space each element will fill. The concept is rather complicated, so I recommend reading the information provided here under the LinearLayout section. I have found the option is most useful when trying to divide the screen into specific ratios between various layout elements.
Android doesn’t provide many options when it comes to font types, so I always assumed I needed to use image resources for any custom fonts until I decided to do a little bit of searching. It turns out that, if you place the font file in the assets folder of your Android project, you can assign it to a TextView but it must be done programmatically. Here is an example of how you would achieve this:
Typeface font = Typeface.createFromAsset(getAssets(), "league_gothic.otf"); ((TextView)findViewById(R.layout.MyTextView)).setTypeface(font);
A lot of time and effort goes into designing and styling Android apps in such a way that you can do it once and reap the benefits across all or most devices. Mix in the complexities of designing both portrait and landscape views (which I didn’t address in this overview), and the work is increasingly more difficult.
I hope these tips make your Android development work at least a little easier and allow you to focus on learning techniques to improve in other areas. Post your favorite Android design tips and tricks in the discussion.