Before Applying the Theme

After Applying the Theme

Download the eclipse project files (zipped) com.blogger.android.meda.bmicalculator-version2.1.zip Access the Source code from github github repo Download the free BMI Calculator app (the latest version) from the Android Market.

<?xml version = "1.0" encoding = "utf-8" ?> <manifest xmlns:android = "http://schemas.android.com/apk/res/android" package = "com.blogger.android.meda.bmicalculator" android:versionCode = "6" android:versionName = "2.1" > <uses-sdk android:minSdkVersion = "4" /> <application android:icon = "@drawable/ic_launcher" android:label = "@string/app_name" > <activity android:label = "@string/app_name" android:name = ".BMICalculatorActivity" android:screenOrientation = "portrait" android:theme = "@android:style/Theme.Black.NoTitleBar" > <intent-filter > <action android:name = "android.intent.action.MAIN" /> <category android:name = "android.intent.category.LAUNCHER" /> </intent-filter > </activity > </application > </manifest >

<LinearLayout android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:background = "@color/colorBG" > <ImageView android:id = "@+id/test_image" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginLeft = "8dip" android:src = "@drawable/ic_launcher" /> <TextView android:id = "@+id/textView0" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_marginBottom = "4dip" android:layout_marginLeft = "15dip" android:layout_marginRight = "5dip" android:layout_marginTop = "9dip" android:text = "@string/app_name" android:textAppearance = "?android:attr/textAppearanceLarge" android:textColor = "@color/colorFonts" /> </LinearLayout >

Custom Title bar

Normal: When the button is neither pressed nor focussed.

Pressed: When the button is pressed.

Focused: When the button is in focus. Normally this state occurs, when a user select and jump between buttons using array keys in their phone.

Set of Images used in theming Widgets

draw9patch editor



Making 9-patch Image (red and blue arrows are added for clarity)

<?xml version = "1.0" encoding = "utf-8" ?> <selector xmlns:android = "http://schemas.android.com/apk/res/android" > <item android:state_focused = "true" android:state_pressed = "false" android:drawable = "@drawable/button_focused" /> <item android:state_focused = "true" android:state_pressed = "true" android:drawable = "@drawable/button_pressed" /> <item android:state_focused = "false" android:state_pressed = "true" android:drawable = "@drawable/button_pressed" /> <item android:drawable = "@drawable/button_normal" /> </selector >

<TableLayout android:id = "@+id/tableLayout1" android:layout_width = "match_parent" android:layout_height = "wrap_content" > <TableRow android:id = "@+id/tableRow1" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginLeft = "5dip" android:layout_marginRight = "5dip" android:layout_marginTop = "15dip" > <TextView android:id = "@+id/textView1" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginRight = "5dip" android:text = "@string/weightLabel" android:textAppearance = "?android:attr/textAppearanceMedium" /> <Spinner android:id = "@+id/spinner1" android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:layout_weight = "2" android:background = "@drawable/bmi_twosided_spinner" android:prompt = "@string/weightLabel" /> <Spinner android:id = "@+id/spinner2" android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:layout_marginLeft = "5dip" android:layout_weight = "1" android:background = "@drawable/bmi_onesided_spinner" android:drawSelectorOnTop = "true" android:entries = "@array/weightUnitsArray" /> </TableRow > <TableRow android:id = "@+id/tableRow2" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginLeft = "5dip" android:layout_marginRight = "5dip" android:layout_marginTop = "15dip" > <TextView android:id = "@+id/textView2" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginRight = "5dip" android:text = "@string/heightLabel" android:textAppearance = "?android:attr/textAppearanceMedium" /> <Spinner android:id = "@+id/spinner3" android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:layout_weight = "2" android:background = "@drawable/bmi_twosided_spinner" android:prompt = "@string/heightLabel" /> <RelativeLayout android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_marginLeft = "5dip" android:layout_weight = "1" > <Spinner android:id = "@+id/spinner4" android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:background = "@drawable/bmi_onesided_spinner" android:entries = "@array/heightUnitsArray" /> <Button android:id = "@+id/button1" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_alignRight = "@+id/spinner4" android:layout_below = "@+id/spinner4" android:layout_marginTop = "15dip" android:background = "@drawable/bmi_button" android:onClick = "calculateClickHandler" android:text = "@string/calculateButton" /> </RelativeLayout > </TableRow > </TableLayout >

New Look and Feel of the app

In my last blog post ( Tutorial: Using Layouts in your Android App ), I showed how to arrange UI widgets in an Android app using different types of layouts. In this blog post I will show how to change the look and feel of an app using custom widget designs. We will continue using the same app we used in the early tutorial - BMI Calculator.Here is the look and feel of the app before and after applying our custom theme.You can see we have changed the background colors, added a custom title bar, and changed the theme of widgets. We have already talked about changing the background color. So here I will show you how to add a custom title bar and how to change the theme of widgets.You can use the following links to download the eclipse project and the android app that we are creating in this tutorial.Before adding a custom title bar, we will remove the default title bar added for our application. This can be easily done by modifying the AndroidManifest.xml in the root directory of the eclipse project. (Have a look at the underlined attribute of the activity element in the following code)Next we add a new linear layout at the top (just after the root linearLayout element) of the res/layout/main.xml file. And inside the layout we will add the project icon and the title.Here the ImageView contain the icon that is shown in the title bar. It is same as the launcher icon in this case (See how to add a launcher icon for the app by following this tutorial, Create Launcher Icon For Your Android App ). In the second text view, we show the string "@string/app_name", which is defined in the "res/values/strings.xml" as "BMI Calculator". And the background of the title bar is set by adding the backgroud attribute to the "@color/colorBG" which is again defined in the strings.xml.These steps would give you the following design to the title of the BMI Calculator App.To get a custom look and feeling for buttons, we can provide custom images for the different states of the button. We will prepare images for the following states of the button.Since we have Button and Spinner widgets, we have to create different images for each of these widget types. Not only that, I thought it is better to have different images for two kind of Spinner widgets. Spinners that show the units (in right corner) only have one downward arrow, where as the spinners show the numbers would have two arrow signs.To prepare the images in photoshop, I started with 50X40 size image, added a rounded rectangle shape, and styled it with bevel and emboss. Here is the set of images I could come up with. (I think they are not that good looking, but just enough for our work).Before applying these images for the widgets, we should convert them in to a format called 9-patch images . This was necessary because with the different sizes of widgets (and different screen sizes of android phones/tablets), the images may stretch giving a unhandy look.With the 9-patch format, we can control the stretching by specifying which part should be repeated when the image is stretched. For example in the onesided_spinner_normal.png shown above, we can specify not to stretch the arrow sign part, while stretching the button.Additionally in 9-patch format, we can specify in which section in the image the text/content should be shown. For example this is useful in images like onesided_spinner_normal.png. When we apply it to a button, we want the text of the button to not cover its arrow sign.To create 9-patch images, android SDK provide 9-patch image editor. You can find it in tools/draw9patch (tools/draw9patch.exe) in the android SDK directory.Lets run the draw9patch editor and open the "onesided_spinner_normal.png" that we prepared earlier.You can see the image is opened in the left side panel. The right hand side panel shows the different looks it will get when it is stretched vertically, horizontally, and diagonally. Here what we do is put some patches (just by clicking) in the border of the image (in the left side panel) as shown below.Patches shown in red arrows (top and left borders) are to say that the image should be stretched only in these sections. For example there is only one patch in the top border. That mean when the image is stretched horizontally, the line of pixel below the patch would be repeated and non of the other pixels will be repeated. And the patches in the left border, make sure the arrow sign and the circle will not be stretched. You can see the sample stretched images in the right hand side panel after our patches are applied.The blue arrows in the above screenshot (bottom and right borders) shows the patches that indicate which part should contain the text (or any other content) of the widget. (Note the patches in the bottom border; we make sure the content will not appear near the arrow sign)When we save the image, the editor will add 9.png (in this case onesided_spinner_normal.9.png) as the extension of the image. This extension is used by android UI to identify 9-patch images and stretched accordingly. We will convert all the prepared images to 9-patch format.Copy all the 9-patch images to the res/drawable directory of the project.To specify the images corresponding to different states (normal, pressed, focussed) of the button widget, we will create an xml called bmi_button.xml with the following content.Here the "@drawable/button_focused" refers to the button_focused.9.png file in the res/drawable directory.Similar to button, we would prepare two more XML files called bmi_onesided_spinner.xml and bmi_twosided_spinner.xml for each of the spinner types. (The content would be the same as above except the drawable attribute should refer to the corresponding 9-patch images).Next we have to set the style XMLs we have created here as the backgroud of the widgets. This is simply done by changing or adding the backgroud attribute to the widgets in main.xml (The UI XML). Here is the updated section of the main.xml. (The changes are underlined.)Here the "@drawable/bmi_button" refers to the bmi_button.xml in the res/drawable directory that we prepared earlier.That is all you have to do. Now run the app in your phone and check the new look and feel.