android ui reference
DESCRIPTION
This is a brief over of the Android UI and the process I went through to make the Admob application for Android.TRANSCRIPT
Android UI ReferenceBy
Matthew Gaunt
Who? What? Why?Hi, I’m Matt Gaunt (@gauntface) I’ve been developing on Android, on and off, for the past 2
years (starting from the 0.9 SDK).
The reason I’ve put this document together is to help others with things I struggled with when I first started out, to help others learn new things with Android UI and to inform people about
some of the new Android design patterns.
This presentation will be suitable for learning, for reference and also great for people just wondering what Android UI is all about.
If you spot something wrong or disagree, then let me know :)
E-mail Address: [email protected]
What Google Want - DashboardLets start off with what Google want
developers to do.
The Dashboard
This is a nice simple, clean and frankly easy to follow design pattern.
Have a panel with 4 - 6 of your app’s main functions.
Example Apps: Twitter, Facebook, Google Places
Note: You don’t have to open your app on this screen
What Google Want - Action BarThe Action Bar
One thing many dev’s do, is needlessy fill the screen, removing the notification bar from the
UI.
The only reason I can think of why someone might do this, is to get rid of the, not so
pretty, title bar.
Instead Google are recommending the Action Bar. The logo on the right should link to the
dashboard and the left side should have buttons relevant to that activity - Perfect :)
Examples - Facebook, Twitter and many more
What Google Want - Quick ActionThe Quick Action
This one I have some reservations about.
It’s a very kool and fun way to give extra functionality in an intuitive way, especially for specific elements on screen (i.e. a list
item or for displaying extra info).
The issue I have is that Twitter has since dropped this, the only other app I know of which uses this is the official Android
Contacts App.
To implement you’re own you’ll most likely want to use an open source library.
Fun, useful and a great idea, but not readily available.
So now what?Well now I’m going to go through *roughly* the development of this UI.
It’s something I’ve been working on recently and this presentation represents the rough process I went through, from start to finish.
Before We StartEvery View should have at least the following states:
NormalFocusedPressedDisabled
For those wondering “What is the focused state?” this is when a user uses the trackball to select a view on the screen. Better to add it in from the start, it’s extra functionality, with little (if any) extra
work.
Making each of these states can be a little tedious, but if you make them all when you first make each View, it isn’t too bad :P
Boring bit said and done, lets get on with it.
Once there was a Button...
The most simple and most widely used View is the Button. So how do we make one? Using the following XML with the
following images.
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/dark_std_button_pressed_bg" /> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/dark_std_button_pressed_bg" /> <item android:state_focused="true" android:drawable="@drawable/dark_std_button_focused_bg" /> <item android:drawable="@drawable/dark_std_button_bg" /></selector> Std.
Focused
Pressed
Focused & Pressed
dark_std_button_pressed_bg
dark_std_button_pressed_bg
dark_std_button_focused_bg
dark_std_button_bg
These actually look different on a
device
...Who met an EditText...
Most apps will need to use an EditText at some point, the reason I wanted to customise mine is to avoid Manufacturer’s custom colour schemes (Orange, Green, Purple and then the
various ROM’s).
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/std_edit_text_focused_pressed_bg" /> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/std_edit_text_pressed_bg" /> <item android:state_focused="true" android:drawable="@drawable/std_edit_text_focused_bg" /> <item android:drawable="@drawable/std_edit_text_bg" /></selector>
Std.
Focused
Pressed
Focused & Pressed
std_edit_text_bg
std_edit_text_focused_bg
std_edit_text_pressed_bg
std_edit_text_focused_pressed_bg
...Who visited the CheckBox...CheckBox is a little bit of extra work, having checked and non-checked
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true" android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/ std_checkbox_checked_focused_pressed" /> <item android:state_checked="false" android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/ std_checkbox_unchecked_focused_pressed" /> <item android:state_checked="true" android:state_focused="true" android:drawable="@drawable/std_checkbox_checked_focused" /> <item android:state_checked="false" android:state_focused="true" android:drawable="@drawable/std_checkbox_unchecked_focused" /> <item android:state_checked="true" android:state_pressed="true" android:drawable="@drawable/std_checkbox_checked_pressed" /> <item android:state_checked="false" android:state_pressed="true" android:drawable="@drawable/std_checkbox_unchecked_pressed" /> <item android:state_checked="true" android:drawable="@drawable/std_checkbox_checked" /> <item android:state_checked="false" android:drawable="@drawable/std_checkbox_unchecked" /></selector>
Std.
Focused
Pressed
Focused & Pressed
std_checkbox_unchecked
std_checkbox_unchecked_pressed
std_checkbox_unchecked_focused
std_checkbox_unchecked_focused_pressed
std_checkbox_checked_focused_pressed
std_checkbox_checked_pressed
std_checkbox_checked_focused
std_checkbox_checked
...But the CheckBox was Fussy...There is one thing you may struggle with when customising your CheckBox.
The View has a Background & a Button property, the difference?The Background defines where content can go (i.e. the text you can set as the CheckBox label)
For my app I have the following:
BackgroundButton
=
label here
Where do I put all this stuff?With a new Android project you’ll get a standard file structure. This is what each folder means :)
+src- All your awesome source code
+res- anim [Animation XML files]- drawable
-Put all your XML drawables here (Button, Checkbox etc.)- drawable-hdpi
- 1.5 * MDPI graphic size (PNG, JPG, Nine-Patch PNG)-drawable-mdpi
- 1 * MDPI graphic size (PNG, JPG, Nine-Patch PNG)-drawable-ldpi
- 0.75 * MDPI graphic size (PNG, JPG, Nine-Patch PNG)-layout-layout-land-values-values-land
+assets+bin+genAndroidManifest.xml
All your images (i.e. for buttons, checkbox etc.) should have a copy of each graphic in drawable-hdpi, -mdpi, -ldpi. (Each copy is for different screen
resolutions (1.5, 1, 0.75 x the graphic size for hdpi, mdpi, ldpi). The point of this is the displayed image should be roughly the same physical size.
Then any xml (the stuff on the previos slides) should be placed in the drawable folder.
In the XML you’ll notice references to @drawable/some_img_name this tells the Android platform to find a drawable with the name some_img_name in one of the drawable folders. Which folder is determined by the system, based on the
screen resolution of the device.
Roman Nurik has said that all XML should go into the drawable folder, I’m sure I have seen gradients appear scaled / manipulated if I put it inside the drawable
folder rather than individually in each folder. So do as Roman says, he’s far wiser than I, but bare in mind it could be the cause of some issues.
I Can Haz Screen Sizes? *For most devices
HDPI - 480 x 800MDPI - 320 x 480LDPI - 240 x 320
Wow - Can I Code Now?
One last bit of XML based fun, but this step will save you a lot of time and frustration.
At the moment to apply your background to a Button, you have to set the background of the button in the layout file, you then have to do that for EACH of your buttons. Wouldn’t it be cool if
you could tell Android to use the same background for all your buttons, but only do it once?
In comes Themes and Styles.We’ll start with Styles and then move on to themes.
Ok, No Code - Styles huh...Lets carry on with our Button, we want a style we can apply to our button.
So what exactly is a style?<style name="admobBtnStyle" parent="android:style/Widget.Button"> <item name="android:background">@drawable/std_btn_stateful</item> <item name="android:textColor">@color/btn_text</item> <item name="android:paddingLeft">@dimen/btn_padding_left_right</item> <item name="android:paddingRight">@dimen/btn_padding_left_right</item> <item name="android:paddingTop">@dimen/btn_padding_top_bottom</item> <item name="android:paddingBottom">@dimen/btn_padding_top_bottom</item> <item name="android:textSize">@dimen/btn_text_size</item> <item name="android:minHeight">@dimen/btn_min_height</item> <item name="android:minWidth">@dimen/btn_min_width</item></style>
Imagine what you might want to set on a button, the background, textColor, textSize, padding . . . you get the picture. Do it in a style, then in a layout you can apply the “style” to a button, rather
than each field individually. This means, one change here applies to all your buttons using this style AND the layout is free to override these values.
I know what you’re thinking - you still need to apply the style to ALL your buttons . . well . . .
Themes FTW... if you apply the style to a Button widget in a Theme, the system automatically applies the style
to all your Buttons - Simples.
<style name="AdmobTheme" parent="android:style/Theme.Light.NoTitleBar"> <item name="android:windowBackground">@color/activity_bg</item> <item name="android:editTextStyle">@style/admobEditText</item> <item name="android:buttonStyle">@style/admobBtnStyle</item> <item name="android:checkboxStyle">@style/admobCheckboxStyle</item></style>
So why have I made you do all this?
In the long run you’ll thank me, there is nothing more soul destroying than going through all your code, altering Buttons to have padding of 2 pixels to the left and right.
For reference, the Styles for the CheckBox & EditText are on the next two slides (Useful for parent styles, the rest you can work out).
CheckBox Style
Yup.
<style name="admobCheckboxStyle" parent="android:style/Widget.CompoundButton.CheckBox"> <item name="android:button">@drawable/std_checkbox_stateful</item> <item name="android:background">@drawable/std_checkbox_bg</item></style>
EditText Style
Double Yup.
<style name="admobEditText" parent="android:Widget.EditText"> <item name="android:background">@drawable/std_edit_text_stateful</item></style>
Last Style Trick - Then PicturesThe last little thing I want to make you aware of.
Say you have two buttons, one is light, one is dark, you want them to share the same parameters apart from the background drawable. Well you can achieve this by having one style being the parent, and the other
extending the parent.
The standard method of doing this is to create a style with same name plus an extension and setting the parent attrib:
<style name="admobBtnStyle" parent="android:style/Widget.Button"> <item name="android:background">@drawable/std_btn_stateful</item> <item name="android:textColor">@color/btn_text</item> <item name="android:paddingLeft">@dimen/btn_padding_left_right</item> <item name="android:paddingRight">@dimen/btn_padding_left_right</item> <item name="android:paddingTop">@dimen/btn_padding_top_bottom</item> <item name="android:paddingBottom">@dimen/btn_padding_top_bottom</item> <item name="android:textSize">@dimen/btn_text_size</item> <item name="android:minHeight">@dimen/btn_min_height</item> <item name="android:minWidth">@dimen/btn_min_width</item></style><style name="admobBtnStyle.Dark" parent="style/admobBtnStyle"> <item name="android:background">@drawable/dark_std_btn_stateful</item></style>
The Action Bar - Code Code CodeThe logo shoud take the user to the dashboard - when this happens you’ll want the other Activities in your app to finish
so be sure to start your Activity with the FLAG_ACTIVITY_CLEAR_TOP flag (See intent.setFlag())
Modal Dialogs - Pah - Utter Rubbish.
Instead, hit my refresh button and it changes to a Progress Bar.
Custom Views aren’t too bad, give them a shot if nothing does what you want. [But use Adapters where you can]
ListViews - Mix it Up a LittleListView 101
1. Personally, I’m not a fan of ListActivity2. Personally, I’m not a fan of helper Adapters3. Use convertView in the getView() method or a kitten will
die for every view you fail to recycle
Hints:cacheColorHint
Set this to an invisible color to stop the fading edges from turning black - #00000000
dividerDrawableYou can change the dividers so they are colored or just a bit different
backgroundThe drawable set to the background will react to different states (pressed, focused, focused pressed)
listSelectorEver wanted to stop the orange highlighting? listSelector = #00000000
Landscape is Easy in AndroidOne thing many developers turn off is landscape rotation. I understand that it’s a little tricky when
you’re Activity dies and starts again, but handle it and you can get some cool effects.
Check out Mark Murphy’s posts on the matter:www.androidguys.com/2008/10/14/rotational-forceson-your-android-app/
Dialogs - Oh God the DialogYou’re not using modal Dialog’s, good, but you do still kinda want to use them, but they kinda
don’t really suite your app.
For me this is a step in the right direction (but not complete), the background image is just a shape (shape is a drawable defined in XML). This is then used in a Theme which is applied in the
AndroidManifest.xml to a reusable Activity.Background<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="@dimen/dialog_rounded_corners" /> <solid android:color="@color/dialog_container_bg_color" /> <stroke android:width="@dimen/dialog_stroke_width" android:color="@color/dialog_stroke_color" /></shape>
Theme<style name="AdmobDialogTheme" parent="android:style/Theme.Dialog"> <item name="android:windowBackground">@drawable/generic_dialog_bg</item> <item name="android:windowFrame">@null</item> <item name="android:windowContentOverlay">@null</item> <item name="android:textViewStyle">@style/admobTextView</item> <item name="android:windowNoTitle">true</item> <item name="android:buttonStyle">@style/admobBtnStyle</item></style>
Last Tid Bit - Cos. . . ...it took me ages to find this out!
How to switch the ProgressBar between dark and light (depending on your parent theme).
<ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content"></ProgressBar>
<ProgressBar android:layout_width="@dimen/action_bar_btn_size" android:layout_height="@dimen/action_bar_btn_size" style="?android:attr/progressBarStyleInverse"></ProgressBar>
.Fin