Android x86
By Richard Leggett on November 29, 2011

Android apps can be just as beautiful as their iOS counterparts. Richard Leggett, co-director of Bitmode Ltd, digs deep into the styling and theming and explains how to use just XML and image files to add a fresh look and feel to your app

It’s sometimes the case that Android apps don’t seem to receive as much love and attention from a designer as they deserve. But Android provides an excellent mechanism for styling, skinning and theming your user interfaces. So with that in mind, let’s take a look at how to make your app stand out. The best bit, almost all of this can be done using just XML and PNG files.

Advertisement

Applying a background Drawable

Drawable is the base class for just about anything that can be drawn on screen. We’re talking images, colours, gradients and a few more complex types that just affect other drawables they are wrapped around (for example, clipping and rotation). Drawables usually come in the form of image files, XML files, or are created through code.

To get a better idea of how a drawable is used, we’ll take a look at specifying a PNG for the background property of a button widget. This will change the button from the default Android style, to our own custom style.

To start, import the “Backgrounds” project into Eclipse by choosing the Import option from the File menu. You’ll need to have downloaded the Android 2.2 SDK via the Android SDK Manager in order to run the project. If this is your first time using the Android SDK with the ADT and Eclipse, please follow the instructions on the following page to get up and running: developer.android.com/sdk/eclipse-adt.html.

 

 

If you run the project you’ll see a standard grey button, and also a shiny green button. Here’s how we specify a different background to use for the button:

  • View source
  • Copy code
  1. <Button
  2.         android:layout_width=”wrap_content”
  3.         android:layout_height=”wrap_content”
  4.         android:text=”Green Button”
  5.         android:background=”@drawable/btn_green” />

Any time you use “@drawable/filename” Android will look at all the “drawables” folders in your project until it finds the best match for the device it’s running on. Notice that when you press down on the button we no longer see a different pushed state. We’ll look at how to supply different states later in Selectors.

9-Patch

Some platforms have the concept of splicing a single image up to be applied to a larger element in such a way that only the middle is stretched. This means the corners, which may be rounded, do not stretch and look blurry or pixelated. In CSS3 this is called border-image, and in Flash, 9-slice.

Android has an advanced version of this called “9-Patch”.  Let’s take a look at our green button being scaled up both with and without using 9-patch.

 

 

There’s an app called draw9patch that can be found with the SDK designed to help with creating these.

 

The draw9patch app

 

On the left you can see a zoomed-in version of our PNG with black lines around the border. You can also see a cross-section where the overlaid light-green lines overlap; this is the part of the image that will scale. In this case it’s just a single pixel. On the right we see various scaled versions of the PNG. Notice how the corners don’t stretch and distort, that’s down to the single green pixel being stretched to fill the space.

To use 9-patch just add a 1-pixel transparent border around your image. Then draw solid black lines that run along the top and left edges to dictate which parts should stretch, and two more black lines right and bottom to indicate where content can sit (make sure you turn off anti-aliasing when drawing these lines, it will complain if any pixel in the border is not 100% black or transparent). Finally, save the file with a “.9.png” extension. Android will automatically assume it is a 9-patch based on the extension.

This means for a button we can use a single PNG to define both how it looks and where content (such as text or icons) appear within it! The ability to define the content area also means you can create an off-centre region for content that ignores say, a drop-shadow, when centering content.

Multiple PPI-screens

The screen you’re looking at is probably running at something like 100 PPI (for the sake of argument, when you read PPI, pixels-per-inch, we can treat it pretty much as DPI, dots-per-inch). So at 100 PPI, if you get right in close to your screen, you can pretty easily see the individual dots. With a Samsung Galaxy Nexus we’re up to 316 PPI; pixels are densely packed into a much smaller space to give it that crisp print-like quality, but that brings with it a challenge.

DPI independence is a key concept when designing for screen; be it phone, computer, tablet or TV. If an icon is 48×48 pixels on your laptop screen, it may physically measure as half an inch wide. On a high DPI (HDPI) phone, the pixels are crammed that much tighter that this same icon would appear less than a quarter of an inch wide. You can imagine that an icon appearing as a tiny square is harder to press, so how do we cater for this wide range of screens?

 

A range of icons that will appear the same physical size on low, medium and high-density screens
A range of icons that will appear the same physical size on low, medium and high-density screens

 

Instead of using pixels or “px” to specify the widths and heights of elements on screen, it’s better to use the “dip” (Device Independent Pixel) unit. This is similar to CSS’ px units which are scaled automatically depending on the DPI of the device. As you may have experienced on your phone, this is why some images can look blurry. Along with text, phone browsers scale px measurements of images up to twice the original width and height to help make existing web pages work without additional effort.

Open up the project “UsingDIPs” to see how we specify dip units for widths and heights in the main.xml layout file.

  • View source
  • Copy code
  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
  3.    android:layout_width=”fill_parent”
  4.    android:layout_height=”fill_parent”
  5.    android:orientation=”vertical” >
  6.     <Button
  7.        android:layout_width=”200dip”
  8.        android:layout_height=”wrap_content”
  9.        android:text=”I’m 200 dips wide” />
  10. </LinearLayout>

In this layout we have a single button with a width of “200dip” (that’s 200px on a MDPI screen, 1.5x or 300px on a HDPI screen). If you open up the layout in the visual editor you’ll see a dropdown box with “3.7in WVGA (Nexus One)” or similar in the top left. You can switch to various other phone screens here, from LDPI to HDPI. Notice how the button width remains the same proportion of the entire screen. Using DIPs we can make sure that this button is the same physical size across devices, and it doesn’t just apply to buttons, any container or widget can accept DIP sizing. The other key property for building scalable layouts is layout_weight, which acts as a kind of percentage-based layout by sharing available space amongst children based on their “weights”, but that is outside of the scope of this article.

Multiple DPI assets

This subject can cause confusion between designers and developers. So to summarise: the DPI property in Photoshop is not important unless you’re printing… all that matters are the width and height in pixels. As a rule, you multiple by 1.5 to go from medium to high to extra-high DPI; so a 48x48px icon should be designed at 72×72 pixels to appear the same physical size on a HDPI phone (eg Galaxy S2), and at 96x96px for XHDPI (eg Galaxy Nexus).

You tell Android what assets to use by putting the files in the relevant drawables folder… drawable-mdpi, drawable-hdpi and so on.

 

Android’s resource folders let you include assets for various device profiles
Android’s resource folders let you include assets for various device profiles

 

Before you worry about having to design three versions of all your assets, Android will automatically attempt to scale up or down assets for you from whichever sizes you provide. Creating larger HDPI versions of assets will simply improve and crisp up existing assets on high-res screens (you may want to focus on enhancing key assets like buttons, and save on file size for things like background textures by not making super high-res versions as this may not be perceivable).

Selectors: The StateListDrawable and ColorStateList

We’re just starting to dig deeper into the power of the Android platform’s graphical abilities. Next up we’ll look at selectors. These are XML files that tell the UI to use a different drawable depending on the state of a widget. For example whether the user is pressing it, whether it is disabled, selected and so on.

We’ll take another widget, the Checkbox. If you want to import the “Selectors” project you can run the demo and see how we can style a CheckBox across multiple states: checked, un-checked, pressed while checked and of course pressed whilst un-checked. There are a few other possible states such as enabled,  selected or focussed (tabbed-to), but for now these four are enough for our purpose.

 

A wood-style checkbox
A wood-style checkbox

 

Along with android:background, the CheckBox widget has another attribute called android:button. Like the background, this can be set to a drawable. In this case, we’re not specifying just one PNG file, we’re specifying a StateListDrawable XML file.

Our checkbox StateListDrawable:

  • View source
  • Copy code
  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2.     <!– checked, pressed –>
  3.     <item android:state_pressed=”true” android:state_checked=”true”
  4.          android:drawable=”@drawable/btn_check_on_pressed”/>
  5.     <!– checked, pressed –>
  6.     <item android:state_pressed=”true” android:state_checked=”false”
  7.          android:drawable=”@drawable/btn_check_off_pressed”/>
  8.     <!– checked –>
  9.     <item android:state_checked=”true”
  10.          android:drawable=”@drawable/btn_check_on”/>
  11.     <!– default –>
  12.     <item android:drawable=”@drawable/btn_check_off” />
  13. </selector>

You may notice that the text also changes colour when we press the checkbox. This is down to a ColorStateList, which you can find in the /res/color/ folder. We simply set the android:textColor property to “@color/checkbox_text_color” instead of a simple hex value and it does the rest.

The wooden checkbox as it appears in code:

  • View source
  • Copy code
  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
  3.    android:layout_width=”fill_parent”
  4.    android:layout_height=”fill_parent”
  5.    android:orientation=”vertical”
  6.    android:background=”#ffffffff” >
  7.     <CheckBox
  8.        android:id=”@+id/checkBox1″
  9.        android:layout_width=”wrap_content”
  10.        android:layout_height=”wrap_content”
  11.        android:text=”CheckBox”
  12.        android:button=”@drawable/checkbox_button”
  13.        android:textColor=”@color/checkbox_text_color” />
  14. </LinearLayout>

Styles and themes

Along with drawables we have the concept of styles and themes. This should be familiar to people that have used CSS, but in Android we use XML to define styles, and styles can inherit from other “parent” styles. Styles apply to widgets and themes apply to activities or apps, a theme is a collection of styles.

Open up the “Styles” project to see the code for this one. We start by creating a “styles.xml” file in the /res/values folder. Android will look in here for our styles.

Our WarningTextView style:

  • View source
  • Copy code
  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <resources>
  3.     <style name=”WarningTextView” parent=”@android:style/Widget.TextView”>
  4.         <item name=”android:background”>#ffff00</item>
  5.         <item name=”android:textColor”>#ff0000</item>
  6.         <item name=”android:textSize”>40sp</item>
  7.         <item name=”android:padding”>10dip</item>
  8.     </style>
  9. </resources>

In the XML we define a single style called WarningTextView, and we inherit from the parent built-in Android style Widget.TextView. We then set about overriding four attributes including the background, the text colour and size, and the inside padding. It’s easy to apply this style to any widget by using the style attribute (notice the style attribute isn’t prefixed with “android:”).

Applying the custom style to a TextView:

  • View source
  • Copy code
  1. <TextView
  2.        style=”@style/WarningTextView”
  3.        android:layout_width=”fill_parent”
  4.        android:layout_height=”wrap_content”
  5.        android:text=”Some SERIOUS words” />

With the style hooked up, here’s how it looks, in all its gaudy glory.

 

Comparing a standard TextView with a custom-styled TextView
Comparing a standard TextView with a custom-styled TextView

 

With styles you can override almost any property and apply it to multiple widgets in order to save you time and effort. Additionally you can override all instances of a component by setting the default style for a widget in an activity.

To do this we need to specify a theme. In the “Themes” project you’ll find a couple of styles defined in styles.xml this time.

Defining a theme to style all buttons in an app:

  • View source
  • Copy code
  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <resources>
  3.     <style name=”MyTheme” parent=”@android:style/Theme.Black”>
  4.         <item name=”android:buttonStyle”>@style/MyButton</item>
  5.     </style>
  6.     <style name=”MyButton” parent=”@android:style/Widget.Button”>
  7.                 <item name=”android:background”>@drawable/btn_green</item>
  8.     </style>
  9. </resources>

This theme specifies a button style to use for all buttons. In order to apply this theme to our app, we must edit the project’s AndroidManifest.xml and specify a theme attribute for either the application tag, or a single activity.

Applying a theme to a whole application:

  • View source
  • Copy code
  1. <application
  2.        android:icon=”@drawable/ic_launcher”
  3.        android:label=”@string/app_name” android:theme=”@style/MyTheme”>

Wrapping up

We’ve seen how 9-patch can make for scalable graphics, but it’s a little known fact that 9-patch actually supports 25 slices! You just add two black lines on each side and it allows two regions to scale. This means you can have an icon in the centre of the image that is unaffected by scaling, reducing the complexity of your layout and increasing the performance of your apps.

If you really want to get a feel for how Android uses drawables to skin its widgets, dive into the Android SDK folder you extracted onto your machine and look for the SDK/platforms/android-8/data/res/drawable-hdpi folder (8 is the SDK version, Android 2.2 in this case). Find the file named “btn_default_normal.9.png”, this is the default button we replaced earlier. Remember the HDPI folder contains higher-res versions of everything in the MDPI folder. Either way these files provide a valuable starting point for creating your own skins.

From here you may want to also look at the styles.xml and themes.xml files inside the Android SDK res folders. These provide valuable information about how the standard widgets are all styled. Additionally we have the fonts. By default the “typeface” attribute only has a few limited options, but through code you can load and use custom font files with a combination of TypeFace.createFromAsset() and TextView.setTypeface().

In the past Android has been plagued by device manufacturers adding their own custom themes which can make your apps look unpredictable, from HTC’s white buttons to Samsung’s black buttons. With Android 4.0 developers can specify the new Holo theme and know that it will not change across devices regardless of the manufacturer’s custom theme. Either way if you have decided you want to customise the style of your widgets, you should go the whole hog, this way you know it will look exactly as you want and really stand out from standard looking apps.

Advertisements
Comments
  1. Carola Cardinalli says:

    I reckon something truly interesting about your website so I saved to fav.

  2. facebook fans says:

    Stubbmled accross your blog site and made a decision to use a quick study, not a few things i usually do, but you have got a great blog. Wonderful to discover a website that isnt stuffed with spam, and really makes some sense. Awesome blog

  3. Harold Riley says:

    Lower right hand corner of the page. Thanks

  4. Backlink says:

    Pretty great post. I just stumbled upon your weblog and wanted
    to say that I’ve really loved surfing around your weblog posts. After all I’ll be subscribing to your rss feed and I hope you write again very soon!

  5. e-tupakka haitat says:

    Very interesting details you have observed , appreciate it for putting up. “You bluffed me I don’t like it when people bluff me. It makes me question my perception of reality.” by Andrew Schneider.

  6. Melanotan ii says:

    As a web-site owner I believe the subject matter here is reallyfantastic. I thank you for your efforts. You should keep it up forever! Good Luck..

  7. Melanotan United States says:

    As a web site owner I believe the material here is reallywonderful. I thank you for your efforts. You should keep it up forever! Good Luck.

  8. teething necklace says:

    I genuinely enjoy looking through on this internet site , it has got fantastic content . “He who sees the truth, let him proclaim it, without asking who is for it or who is against it.” by Henry George.

  9. film izle says:

    you will be definitely variety 1 admin your running a blog is remarkable i always examine your blog i am certain you will probably be the most effective

  10. los angeles attorney says:

    Woh I your content , bookmarked ! .

  11. breast cancer secondary sites says:

    Very good blog! Do you have any tips and hints for aspiring writers? I’m hoping to start my own blog soon but I’m a little lost on everything. Would you suggest starting with a free platform like WordPress or go for a paid option? There are so many choices out there that I’m completely confused .. Any ideas? Kudos!

  12. auto approved blog says:

    Can I say that of a relief to locate somebody that in fact knows what theyre talking about more than the internet. You undoubtedly know how to bring a challenge to light and produce it essential. The diet ought to look at this and recognize why side within the story. I cant believe youre not far more well-liked when you absolutely provide the gift.

  13. Sex Chat says:

    You have remarked very interesting details! ps decent internet site.

  14. music licensing deals says:

    Your blog is great. Thanks for your offerings, and the information you’ve posted.

  15. Emmie Wilner says:

    Only a smiling visitant here to share the love (:, btw great design. “Make the most of your regrets… . To regret deeply is to live afresh.” by Henry David Thoreau.

  16. astronomy song lyrics says:

    Hey this is somewhat of off topic but I was wondering if blogs use WYSIWYG editors or if you have to manually code with HTML. I’m starting a blog soon but have no coding knowledge so I wanted to get advice from someone with experience. Any help would be enormously appreciated!

  17. baby boomer retirement says:

    Howdy very cool blog!! Guy .. Excellent .. Wonderful .. I will bookmark your web site and take the feeds additionally…I’m glad to seek out a lot of helpful information right here within the submit, we’d like work out more techniques in this regard, thanks for sharing.

  18. fetish porn videos says:

    Greetings thanks for fantastic publish i was seeking for this concern previous 2 times. I’ll look for future valuable posts. Have fun admin.

  19. Cheats for Vampire's Curse Island says:

    I am not rattling superb with English but I get hold this very leisurely to understand.

  20. eliminating credit card bills says:

    I am really inspired together with your writing abilities as smartly as with the structure on your blog. Is that this a paid subject matter or did you modify it your self? Anyway keep up the excellent high quality writing, it’s rare to see a nice blog like this one today.

  21. Carmina says:

    Very interesting topic, appreciate it for putting up.

  22. iowa attack basketball says:

    I think you have mentioned some very interesting details , thankyou for the post.

  23. four micro onde says:

    I got what you intend, appreciate it for posting .Woh I am delighted to find this website through google. “The test and use of a man’s education is that he finds pleasure in the exercise of his mind.” by Carl Barzun.

  24. fans for you and me says:

    humanitarian familial banko affais femmes madness hellenic refugio Fabien

  25. credit card holder says:

    You have remarked very interesting details! ps decent web site.

  26. Free Credit Score Scam says:

    I read so many poorly written articles with dull content on this topic that I was pleasantly surprised by yours. It’s great to know there’s at least one writer that writes interesting and unique material.

  27. coach credit card holder says:

    I like what you guys are up too. Such smart work and reporting! Carry on the excellent works guys I have incorporated you guys to my blogroll. I think it’ll improve the value of my site :).

  28. best hybrid cars says:

    Very interesting topic, thank you for putting up.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s