Styling the ActionBar – Part 4
In the previous article in this series we applied a style to the navigation Spinner and its associated drop down ListView, but found that this style did not get applied to the Spinner that we added manually using the actionViewClass attribute of the MenuItem definition in our menu XML. In this article we’ll find out why.
SO far in this series, the examples have followed quite a similar formula: Define a style, then apply it to an item via the theme. In this case we appear to have applied the style correctly to one Spinner control, but not the other. This is where applying styles to the ActionBar can begin to get a little confusing: When we get something working, we can look at our styles and theme and it makes perfect sense; but when things aren’t working, we can still look at our styles and theme and it makes perfect sense – but it just doesn’t work!
If you are in this situation, the best advice is to find working code which does what you’re trying to do. Once of the best sources of this is the Android source and you can look at the styles and themes baked in to the core OS itself here.
So, back to our problem. If we check out the behaviour of the second drop down, it’s actually pretty close to what we want:
The Spinner itself looks OK, and the selector is correct, it is just the background of the drop down that is wrong. Let’s have a look at out theme:
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar"> <item name="android:actionBarStyle">@style/ActionBar</item> <item name="android:actionBarTabStyle">@style/ActionBarTabStyle</item> <item name="android:popupMenuStyle">@style/PopupMenu</item> <item name="android:dropDownListViewStyle">@style/DropDownListView</item> <item name="android:actionBarWidgetTheme">@style/Theme.stylingactionbar.widget</item> <item name="android:actionDropDownStyle">@style/DropDownNav</item> <item name="android:spinnerDropDownItemStyle">@style/DropDownItem</item> <item name="android:spinnerItemStyle">@style/SpinnerItem</item> </style>
We are applying some specific styles to Spinners in general which explains why the style gets correctly applied to some aspects of both Spinners; we can also see the dropDownListViewStyle which is applying the selector. The key thing appears to be actionDropDownStyle which applies a style with a setting for popupBackground which applies a green panel that was generated by ActionBar Style Generator:
<style name="DropDownNav" parent="@android:style/Widget.Holo.Spinner"> <item name="android:background">@drawable/spinner_background_ab_stylingactionbar</item> <item name="android:popupBackground">@drawable/menu_dropdown_panel_stylingactionbar</item> <item name="android:dropDownSelector">@drawable/selectable_background_stylingactionbar</item> </style>
So, it would appear that this popupBackground is not getting set on the drop down of our second Spinner.
The simplest way to resolve this, is to actually apply a background specifically to both drop downs, and we can do this through the common style which sets the selector correctly. So let’s modify dropDownListViewStyle and explicitly set a background colour on our drop down ListViews:
<style name="DropDownListView" parent="@android:style/Widget.Holo.ListView.DropDown"> <item name="android:listSelector">@drawable/selectable_background_stylingactionbar</item> <item name="android:background">@color/sa_green</item> </style>
If we run this, we can see that the background is now correct:
So we’ve done it, haven’t we. Actually we haven’t. We’ve got a very close approximation, but if we look carefully we can see small discrepancies.
The navigate Spinner doesn’t have a line below it, whereas the second one does:
When we click on the navigation Spinner, it has a green highlight, but the second Spinner has the default blue highlight:
Finally, the drop down of the navigation Spinner has quite a soft drop shadow, but the second Spinner has a much stringer one:
This is another way that styling the ActionBar can become frustrating, you feel that you’re almost there, but then start spotting these minor discrepancies. What this is actually telling us is that we are not applying the same style to both Spinners. There are certain defaults which are getting applied to the second Spinner, but we are not actually applying the same style as is being applied to the navigation Spinner. Think back to when we looked at our theme. The key line is:
This applies the correct style to the navigation but this is not getting applied to the second one. Remember in the previous article when we applied a style to the overflow menu? The technique we used was to apply an
<style name="Theme.stylingactionbar.widget" parent="@android:style/Theme.Holo"> <item name="android:popupMenuStyle">@style/PopupMenu</item> <item name="android:dropDownListViewStyle">@style/DropDownListView</item> <item name="android:spinnerStyle">@style/DropDownNav</item> </style>
We use the same style as we have used for the navigation Spinner. We can also remove the background that we added to DropDownListView as this is no linger needed if we apply a consistent style. Now everything works, and we have a uniform look across the Spinners:
We’re almost there, but the eagle eyed will have spotted that there is still a small discrepancy: The dividers of the ListViews do not match. This is because of the light theme with a dark action bar that we’re using. The easy fix for this is to define an explicit divider in our common style:
<style name="DropDownListView" parent="@android:style/Widget.Holo.ListView.DropDown"> <item name="android:listSelector">@drawable/selectable_background_stylingactionbar</item> <item name="android:divider">@color/pressed</item> <item name="android:dividerHeight">1dp</item> </style>
This gives us a consistent divider:
Finally we have both of our Spinners correctly styled.
If we compare the project code to how it was at the beginning of this article, we’ve actually added 3 lines of XML to our style, that’s all. We did go down a blind alley in the process, but this really sums up how getting ActionBar styling working correctly can be in reality: Lots of effort to find the correct, rather simple solution.
In the next part of this series we’ll look at applying a style to the search EditText widget in our ActionBar.
The source code for this article can be found here.
© 2012, Mark Allison. All rights reserved. This article originally appeared on Styling Android.
Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License
Styling the ActionBar – Part 4 by Styling Android, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. Terms and conditions beyond the scope of this license may be available at blog.stylingandroid.com.