Android Developer

Los Angeles Freelance Developer

Android Developer header image 2

Styling Android With Defaults

January 8th, 2012 · 25 Comments · Android, OOP, Styling

According to Android’s own documentation, there is no documentation for styling Android. You’d think with the power of Google and huge market penetration, the Android team with have the commitment by now to document their code and features, but that’s another story. So what does Android officially say about styling? “Go read the source code.” Well, that’s a terrible stance and it leaves a developer guessing for hours, days, and even weeks. The things I’m going to share in this post took me quite a while to learn and I wish someone showed me early on. They will speed up the process and allow your styling to be more flexible to change. The rest of this article will talk about setting up a default theme to globally style your application.

Disclaimer:
If you’re not already quite familiar with styling Android this post is not for you. Seriously, don’t read it, you’ll just end up hating me. Keeping true to this blog, below I’m going to talk about an approach not a walk through of how  and what. If this is you, now would be a good time to read what documentation there is on styling Android and come back and read this after you have a basic understanding of styles and themes.

It wasn’t until I released several applications that I learned how to style Android properly. I say properly because I was indeed styling my applications but I wasn’t styling them in a flexible manner that would easily accommodate change. I was applying the style tag to each and every widget that needed styled.  When a style changed or I needed something different, I had to go back through each element and reapply a new style tag to it. Think about all the widgets/view there are in an application. Now think about going through each one and applying a style tag. Yuck, this took a lot of time and I would miss widgets here and there. This approach I was taking to styling Android was very rigid, brittle and I was repeating myself. As an OO developer this bugged me. I wasn’t creating my own theme, I was using Android’s theme of Dark or Light and styling each widget as needed. This is and was not good.

So let’s take a look at the screenshot of the styled app below and download the source code.

Now obviously from the screenshot, you love this app and want to make one just like it. Cool. I’m going to explain the 2 important concepts right now that took me forever to learn. Let’s check out the code-screenshot below to get started.

Let talk about the red arrows first. An Android Theme has references to styles that define the default skin/style for each Widget. What do I mean by that? For example, look at line 19 in the screenshot: <item name=”android:buttonStyle”>@style/Button</item>. This tells our app that all buttons will have the default style as defined by our style “Button.” This means you don’t have to go through each and every button and apply the style tag. It comes with this default skin. Awesome, right? Yuppers, and this is available for each widget in Android. You can see right below that we do the same for our ListView giving the dividers a default height of 5dp and a blueish color. And you can keep doing this for each widget you want to custom style until your heart’s content. Besides rapidly speeding up the process for styling an Android application this approach also creates consistency in your application. And if you think about it, it is the approach that Android is taking itself. That alone seems like a good reason to use this approach.

 How do I know what the widget names are called so I can style them?

Yup, this is the part where Android says there is no or lacking documentation. You really do have to read the source code, but it isn’t that bad. Let’s check out two files called themes.xml and styles.xml. Go to your Android sdk installation folder and then follow this path: {Android}/sdk/platforms/android-8/data/res/values. In here you will see a file called themes.xml. Go ahead and open it and look at the tag that says <style name=”Theme”> or check out the code below.

<style name="Theme">
        <item name="colorForeground">@android:color/bright_foreground_dark</item>
        <item name="colorForegroundInverse">@android:color/bright_foreground_dark_inverse</item>
        <item name="colorBackground">@android:color/background_dark</item>
        <item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>
        <item name="disabledAlpha">0.5</item>
        <item name="backgroundDimAmount">0.6</item>
 
        <!-- Text styles -->
        <item name="textAppearance">@android:style/TextAppearance</item>
        <item name="textAppearanceInverse">@android:style/TextAppearance.Inverse</item>
 
        <item name="textColorPrimary">@android:color/primary_text_dark</item>
        <item name="textColorSecondary">@android:color/secondary_text_dark</item>
        <item name="textColorTertiary">@android:color/tertiary_text_dark</item>
        <item name="textColorPrimaryInverse">@android:color/primary_text_light</item>
        <item name="textColorSecondaryInverse">@android:color/secondary_text_light</item>
        <item name="textColorTertiaryInverse">@android:color/tertiary_text_light</item>
        <item name="textColorPrimaryDisableOnly">@android:color/primary_text_dark_disable_only</item>
        <item name="textColorPrimaryInverseDisableOnly">@android:color/primary_text_light_disable_only</item>
        <item name="textColorPrimaryNoDisable">@android:color/primary_text_dark_nodisable</item>
        <item name="textColorSecondaryNoDisable">@android:color/secondary_text_dark_nodisable</item>
        <item name="textColorPrimaryInverseNoDisable">@android:color/primary_text_light_nodisable</item>
        <item name="textColorSecondaryInverseNoDisable">@android:color/secondary_text_light_nodisable</item>
        <item name="textColorHint">@android:color/hint_foreground_dark</item>
        <item name="textColorHintInverse">@android:color/hint_foreground_light</item>
        <item name="textColorSearchUrl">@android:color/search_url_text</item>
 
        <item name="textAppearanceLarge">@android:style/TextAppearance.Large</item>
        <item name="textAppearanceMedium">@android:style/TextAppearance.Medium</item>
        <item name="textAppearanceSmall">@android:style/TextAppearance.Small</item>
        <item name="textAppearanceLargeInverse">@android:style/TextAppearance.Large.Inverse</item>
        <item name="textAppearanceMediumInverse">@android:style/TextAppearance.Medium.Inverse</item>
        <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Small.Inverse</item>
        <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.SearchResult.Title</item>
        <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.SearchResult.Subtitle</item>
 
        <item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item>
 
        <item name="candidatesTextStyleSpans">@android:string/candidates_style</item>
 
        <item name="textCheckMark">@android:drawable/indicator_check_mark_dark</item>
        <item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_light</item>
 
        <!-- Button styles -->
        <item name="buttonStyle">@android:style/Widget.Button</item>
 
        <item name="buttonStyleSmall">@android:style/Widget.Button.Small</item>
        <item name="buttonStyleInset">@android:style/Widget.Button.Inset</item>
 
        <item name="buttonStyleToggle">@android:style/Widget.Button.Toggle</item>
 
        <!-- List attributes -->
        <item name="listPreferredItemHeight">64dip</item>
        <!-- @hide -->
        <item name="searchResultListItemHeight">58dip</item>
        <item name="listDivider">@drawable/divider_horizontal_dark</item>
        <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator</item>   
 
        <item name="listChoiceIndicatorSingle">@android:drawable/btn_radio</item>
        <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check</item>    
 
        <item name="expandableListPreferredItemPaddingLeft">40dip</item>
        <item name="expandableListPreferredChildPaddingLeft">
                ?android:attr/expandableListPreferredItemPaddingLeft</item>
 
        <item name="expandableListPreferredItemIndicatorLeft">3dip</item>
        <item name="expandableListPreferredItemIndicatorRight">33dip</item>
        <item name="expandableListPreferredChildIndicatorLeft">
                ?android:attr/expandableListPreferredItemIndicatorLeft</item>
        <item name="expandableListPreferredChildIndicatorRight">
                ?android:attr/expandableListPreferredItemIndicatorRight</item>
 
        <!-- Gallery attributes -->
        <item name="galleryItemBackground">@android:drawable/gallery_item_background</item>
 
        <!-- Window attributes -->
        <item name="windowBackground">@android:drawable/screen_background_dark</item>
        <item name="windowFrame">@null</item>
        <item name="windowNoTitle">false</item>
        <item name="windowFullscreen">false</item>
        <item name="windowIsFloating">false</item>
        <item name="windowContentOverlay">@android:drawable/title_bar_shadow</item>
        <item name="windowShowWallpaper">false</item>
        <item name="windowTitleStyle">@android:style/WindowTitle</item>
        <item name="windowTitleSize">25dip</item>
        <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
 
        <!-- Dialog attributes -->
        <item name="alertDialogStyle">@android:style/AlertDialog</item>
 
        <!-- Panel attributes -->
        <item name="panelBackground">@android:drawable/menu_background</item>
        <item name="panelFullBackground">@android:drawable/menu_background_fill_parent_width</item>
        <item name="panelColorBackground">#fff</item>
        <item name="panelColorForeground">?android:attr/textColorPrimaryInverse</item>
        <item name="panelTextAppearance">?android:attr/textAppearanceInverse</item>
 
        <!-- Scrollbar attributes -->
        <item name="scrollbarFadeDuration">250</item>
        <item name="scrollbarDefaultDelayBeforeFade">300</item>
        <item name="scrollbarSize">10dip</item>
        <item name="scrollbarThumbHorizontal">@android:drawable/scrollbar_handle_horizontal</item>
        <item name="scrollbarThumbVertical">@android:drawable/scrollbar_handle_vertical</item>
        <item name="scrollbarTrackHorizontal">@null</item>
        <item name="scrollbarTrackVertical">@null</item>
 
        <!-- Widget styles -->
        <item name="absListViewStyle">@android:style/Widget.AbsListView</item>
        <item name="autoCompleteTextViewStyle">@android:style/Widget.AutoCompleteTextView</item>        
        <item name="checkboxStyle">@android:style/Widget.CompoundButton.CheckBox</item>
        <item name="dropDownListViewStyle">@android:style/Widget.ListView.DropDown</item>
        <item name="editTextStyle">@android:style/Widget.EditText</item>
        <item name="expandableListViewStyle">@android:style/Widget.ExpandableListView</item>
        <item name="expandableListViewWhiteStyle">@android:style/Widget.ExpandableListView.White</item>
        <item name="galleryStyle">@android:style/Widget.Gallery</item>
        <item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView</item>
        <item name="gridViewStyle">@android:style/Widget.GridView</item>
        <item name="imageButtonStyle">@android:style/Widget.ImageButton</item>
        <item name="imageWellStyle">@android:style/Widget.ImageWell</item>
        <item name="listViewStyle">@android:style/Widget.ListView</item>
        <item name="listViewWhiteStyle">@android:style/Widget.ListView.White</item>
        <item name="popupWindowStyle">@android:style/Widget.PopupWindow</item>
        <item name="progressBarStyle">@android:style/Widget.ProgressBar</item>
        <item name="progressBarStyleHorizontal">@android:style/Widget.ProgressBar.Horizontal</item>
        <item name="progressBarStyleSmall">@android:style/Widget.ProgressBar.Small</item>
        <item name="progressBarStyleSmallTitle">@android:style/Widget.ProgressBar.Small.Title</item>
        <item name="progressBarStyleLarge">@android:style/Widget.ProgressBar.Large</item>
        <item name="progressBarStyleInverse">@android:style/Widget.ProgressBar.Inverse</item>
        <item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small.Inverse</item>
        <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large.Inverse</item>
        <item name="seekBarStyle">@android:style/Widget.SeekBar</item>
        <item name="ratingBarStyle">@android:style/Widget.RatingBar</item>
        <item name="ratingBarStyleIndicator">@android:style/Widget.RatingBar.Indicator</item>
        <item name="ratingBarStyleSmall">@android:style/Widget.RatingBar.Small</item>
        <item name="radioButtonStyle">@android:style/Widget.CompoundButton.RadioButton</item>
        <item name="scrollViewStyle">@android:style/Widget.ScrollView</item>
        <item name="horizontalScrollViewStyle">@android:style/Widget.HorizontalScrollView</item>
        <item name="spinnerStyle">@android:style/Widget.Spinner</item>
        <item name="starStyle">@android:style/Widget.CompoundButton.Star</item>
        <item name="tabWidgetStyle">@android:style/Widget.TabWidget</item>
        <item name="textViewStyle">@android:style/Widget.TextView</item>
        <item name="webTextViewStyle">@android:style/Widget.WebTextView</item>
        <item name="webViewStyle">@android:style/Widget.WebView</item>
        <item name="dropDownItemStyle">@android:style/Widget.DropDownItem</item>
        <item name="spinnerDropDownItemStyle">@android:style/Widget.DropDownItem.Spinner</item>
        <item name="spinnerItemStyle">@android:style/Widget.TextView.SpinnerItem</item>
        <item name="dropDownHintAppearance">@android:style/TextAppearance.Widget.DropDownHint</item>
        <item name="keyboardViewStyle">@android:style/Widget.KeyboardView</item>
        <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.QuickContactBadge.WindowSmall</item>
        <item name="quickContactBadgeStyleWindowMedium">@android:style/Widget.QuickContactBadge.WindowMedium</item>
        <item name="quickContactBadgeStyleWindowLarge">@android:style/Widget.QuickContactBadge.WindowLarge</item>
        <item name="quickContactBadgeStyleSmallWindowSmall">@android:style/Widget.QuickContactBadgeSmall.WindowSmall</item>
        <item name="quickContactBadgeStyleSmallWindowMedium">@android:style/Widget.QuickContactBadgeSmall.WindowMedium</item>
        <item name="quickContactBadgeStyleSmallWindowLarge">@android:style/Widget.QuickContactBadgeSmall.WindowLarge</item>
 
        <!-- Preference styles -->
        <item name="preferenceScreenStyle">@android:style/Preference.PreferenceScreen</item>
        <item name="preferenceCategoryStyle">@android:style/Preference.Category</item>
        <item name="preferenceStyle">@android:style/Preference</item>
        <item name="preferenceInformationStyle">@android:style/Preference.Information</item>
        <item name="checkBoxPreferenceStyle">@android:style/Preference.CheckBoxPreference</item>
        <item name="yesNoPreferenceStyle">@android:style/Preference.DialogPreference.YesNoPreference</item>
        <item name="dialogPreferenceStyle">@android:style/Preference.DialogPreference</item>
        <item name="editTextPreferenceStyle">@android:style/Preference.DialogPreference.EditTextPreference</item>
        <item name="ringtonePreferenceStyle">@android:style/Preference.RingtonePreference</item>
        <item name="preferenceLayoutChild">@android:layout/preference_child</item>
 
        <!-- Search widget styles -->
        <item name="searchWidgetCorpusItemBackground">@android:color/search_widget_corpus_item_background</item>
    </style>

This is the default style of an Android application. And this is how each widget has a default style applied to it. More importantly, look at all those items you can style yourself! To change any of them, all you have to do is set the appropriate attribute to reference your own custom style and then that widget is globally styled in your application. Let’s look at one of the Android’s defaults, textViewStyle, which is what gives the default appearance to the TextViews. Here you can see that the textViewStyle attribute points to an Android style of Widget.TextView located in the styles.xml file. Open it, and you’ll see this

<style name="Widget.TextView">
   <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
</style>

This is how Android styles itself to have defaults for each widget. Pretty cool, eh?

So how about them blue arrows in that diagram above? I like blue and you haven’t even talked about them at all yet.

Those are references to attributes in the theme. Check out line 33 that has the blue arrow, the textColor property on TextApperance.Large. You can see that the textColor value is a reference to the color value held in the Theme’s textColorTerinary attribute that we’ve set ourselves. And here was my stumbling block for a while: even though the syntax has the android namespace on it of ?android:attr/textColorTertiary, it’s not a reference to the original Android’s Theme attribute value, but the one we just defined! This is very handy. For instance, we don’t have to define our own style for Android’s TextView because its textAppearance property has a reference to the textAppearanceSmall property of the Theme. And since we just defined our own value for that all the TextViews now take on our new style. Woot woot!

 So what does all this mean and what is the meaning life, the universe, everything?

42 and this is general approach you should be taking to style your apps on Android. Don’t go through and add the style=”@style/FooBar” to each and every ListView or Button or TextView like I once did and I see a lot of other developers doing. Define a default style for them in your application’s theme, set it in your Manifest file, and then custom style each Widget as needed. This is the approach Android uses natively and so should you.

Sources:
Click here to download the example files

Edit: Screenshot for @Norfeldt to show how to set the theme in the Eclipse Graphical Layout view.

 

Tags: ·····

25 responses so far ↓

  • 1 Brian Williammee // Jan 9, 2012 at 4:25 am

    “Don’t go through and add the style=”@style/FooBar” to each and every ListView or Button or TextView.”

    Been there / done that. It’s not fun. Thanks for this. I’ve got you bookmarked and will make use of this on my next project.

  • 2 musselwhizzle // Jan 9, 2012 at 4:35 am

    @Brian, Thanks for the nice comment. I thought this was a nice feature not talked much about in the community and wanted to get the info out the community. Glad you enjoyed it. Cheers.

  • 3 Norfeldt // Jan 21, 2012 at 4:40 pm

    Thank you so MUCH!!! I still need to practice it a lot since these stylesheet don’t do autocomplete or suggestions, but I know I will find it handy since most of my coding time goes to the UI.

  • 4 Norfeldt // Jan 22, 2012 at 12:34 pm

    A very basic question: How do I view my theme in the WYSIWYG Eclipse graphical layout editor so I don’t have to compile and run the app all the time to see the result.
    I can only choose the basic android themes and not the one I have created.
    http://dl.dropbox.com/u/3216968/styling%20android.png

  • 5 musselwhizzle // Jan 22, 2012 at 3:37 pm

    @Norfeldt, Hi buddy, I added a screenshot at the end of the post. I’m not sure why your theme isn’t showing in the list, but you can see in my screenshot attached the theme shows up and I just select it.

  • 6 Norfeldt // Jan 24, 2012 at 8:29 am

    I just updated the ADT in eclipse and the new version seems to support own custom themes. Thanks a lot!

  • 7 Android: Starting a New Project // Apr 11, 2012 at 11:31 pm

    […] Styling Android With Defaults […]

  • 8 Yohei Maeda // May 16, 2012 at 12:03 am

    Thanks!!
    I wanted the documents like this!!

  • 9 tweaking Android built-in UI » Eason.C's Blog // Oct 1, 2012 at 11:48 pm

    […] Styling Android With Defaults – Android Developer […]

  • 10 Steve Cartoon // Oct 29, 2012 at 5:44 pm

    Absolutely essential tutorial, this! This saves me a WORLD of time and effort!
    I suppose the reason for this being largely undocumented would have been it’s very easy for a person new at this to bung the whole thing up? This is definitely not a beginning-level subject, but somehow it should be in the first-year curriculum. Maybe just after the first couple of tutorials where you’re getting stuff to appear on the screen, but before you learn about Intents and activity switching?
    Anyways, enough reflection. Thank you very kindly for this brilliant tutorial!

  • 11 musselwhizzle // Oct 29, 2012 at 5:49 pm

    @Steve, Glad you enjoyed it. Cheers!

  • 12 Joel // Dec 13, 2012 at 12:59 pm

    Have you noticed any problems getting styles to work on newer devices? I copied your code almost exactly, and it runs fine on my Gingerbread device, but the styles are totally ignored on my Jelly Bean device.

  • 13 musselwhizzle // Dec 13, 2012 at 1:24 pm

    Hi Joel, I haven’t experienced anything like this. It always runs fine for me across different OS versions.

  • 14 androidrant // Mar 19, 2013 at 7:10 am

    great tip! a life saver when the client wants you to customize app appearance! thanks for this :)

  • 15 sam // Apr 15, 2013 at 1:01 am

    you’ve been a great help. I was stuck for 3 days trying to figure out how to change the dividers for the overflow menu and this lead me to the proper solution

  • 16 Kinjal Patel // Apr 30, 2013 at 7:14 pm

    Thanks for providing such a useful information. Its really helpful. I have one question like if I override the native text appearance how can i use native one ?

    Thanks,
    Kinjal Patel

  • 17 musselwhizzle // Apr 30, 2013 at 8:55 pm

    Hi Kinjal, I wouldn’t think of it as overriding so much as just changing reference for the default. If you need to access the original just access it directly with @android:style/Widget.Whatever.Whatever

  • 18 scott // May 14, 2013 at 12:30 pm

    Thanks for the help. Your source code compiles and runs without a hitch. But the graphical layout editor in Eclipse gags on the xml layout file with this error:

    android.content.res.Resources$NotFoundException
    Exception details are logged in Window > Show View > Error Log
    The following classes could not be found:
    – TextView (Change to android.widget.TextView, Fix Build Path, Edit XML)

    In the error log we have:

    main.xml: android.content.res.Resources$NotFoundException in com.android.ide.eclipse.adt.

    I’m running Juno, Release 2, and using ADT 21.1.0.

    Not really a bother for me as I rarely used the graphical layout editor, but just letting you know.

    -s

  • 19 AlexS // Oct 28, 2013 at 10:01 am

    Thank you for that great article. Now I understand this style-thingies much better (although I will still have to spend some time with the sherlock-themes…

  • 20 William Patchen // Feb 10, 2014 at 3:37 pm

    Thanks for the great article. You’re right on with the glaring omission of information like this in the official docs. Further proof of the fundamental difference between android and iOS: iOS is lead by design; android android is lead from engineering

  • 21 Chris // Apr 1, 2014 at 11:33 am

    I’m trying to style a switch control, but I don’t see that anywhere in the theme.xml file. I see checkboxes and radiobuttons, but no switch.
    Any idea what I use for that?

    I’m still a bit confused on all this, but I think with trial and error I’ll get the hang of it.

    Thanks

  • 22 Aung // Apr 6, 2014 at 12:23 am

    Hi Josh, really love your posts.
    Now, start seeing a big picture of the android projects’ architecture.

    Can you make a few posts related to prototyping and designing the mobile application (not related to actual programming) ? I mean in ui / ux level. Or can you point me I can read decent articles like yours ?

    Thanks a lot.

  • 23 Rob // Sep 25, 2014 at 2:03 am

    Wow! Thank you! I found hundreds of tutorials showing the basics of styling and theming, but absolutely NONE which showed how to auto-apply styles to standard widgets in a custom theme without applying the style tag to each and every widget! If I ever meet you, I’ll get you a large drink!

  • 24 musselwhizzle // Sep 25, 2014 at 2:10 am

    I’m going to hold you to that drink. :)

  • 25 Nagaraj // Mar 2, 2016 at 4:10 am

    Thank you so much!

    I have wasted two days of my valuable time in understanding more about Themes and Styles but I could not understood it properly. But above document clears all my doubts which I have had from past one year.

    Cheers!!

Leave a Comment