There were two great posts covering the usage of styles recently, one by Dave Smith and the other by Dan Lew. Dave’s post warns not to be over-zealous with extracting properties styles; just because you can put a certain view property in a style, doesn’t mean you should. Dan’s post offers a set of guidelines to follow to keep your styles from becoming messy, and covers some common pitfalls! Do check them out.
This post will explain how we use styles at Novoda, and why we use them in the way we do.
What are styles? What are themes?
For a good overview of what styles and themes are, check out the Styles and Themes page on the Android Developers website. In short, they’re like CSS files for web – a way to define how your views look, separate from your layouts.
A working example
We’ll take a really simple example to show how we’ve used styles.
The screen has two elements – a
Toolbar and a
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.Toolbar android:id="@+id/action_bar" style="@style/Wutson.Toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" /> <android.support.v7.widget.RecyclerView android:id="@+id/trending_shows_list" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
You’ll see above, we apply the
Wutson.Toolbar style to the
Toolbar, but we haven’t got a style for the
RecyclerView nor the root.
RecyclerView in this case is just a container – it has no padding, no background color, just the ID, the width and the height. It is backed by an adapter which creates instances of
TrendingShowsItemView (which is just a subclass of
FrameLayout for now):
<?xml version="1.0" encoding="utf-8"?> <com.ataulm.wutson.TrendingShowsItemView xmlns:android="http://schemas.android.com/apk/res/android" style="@style/TrendingShows.Item" android:layout_width="wrap_content" android:layout_height="wrap_content" />
Here we’ve got a style applied too. This will be applied everywhere a
TrendingShowsItemView is inflated using this layout.
With the actual styles themselves, we split them into different files based on where they are used. We add a namespace for each file; here the dot notation is (ab)used just to provide context whenever we use a particular style.
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="TrendingShows" /> <style name="TrendingShows.Item"> <item name="android:paddingLeft">@dimen/trending_shows_item_padding_left</item> <item name="android:paddingTop">@dimen/trending_shows_item_padding_top</item> <item name="android:paddingRight">@dimen/trending_shows_item_padding_right</item> <item name="android:paddingBottom">@dimen/trending_shows_item_padding_bottom</item> </style> </resources>
Additionally, we define the themes that are set in the AndroidManifest, and also styles which are not screen-specific (e.g. a base
Button style) in another file:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="Wutson" /> <style name="Wutson.Base" parent="Theme.AppCompat.Light.NoActionBar" /> <style name="Wutson.Toolbar"> <item name="android:background">@drawable/bg_actionbar</item> <item name="navigationIcon">@drawable/ic_nav</item> </style> </resources>
The rules are simple:
- For each screen, XYZ, add an XML resource file,
- Extract all eligible attributes as a style (considering scope, as per Dave Smith’s article – any attribute with layout_xyz should not be extracted), regardless of whether the style is only used once
- Name your base styles with the
- Delete your unused styles(!)
The last rule is the most important – there’s nothing worse than long style files, apart from unnecessarily long style files.
Ugh, must I?
It’s up to you and your team.
The reason we do it at Novoda is because we’re typically working on several different projects at once and it makes it easier for people to pair-program or join another project; for us, conventions with Android resources is just as important as using a common style for our Java code.
I’m going to quote Dan’s conclusion so I can comment on it:
The unifying element of these rules are to be careful and thoughtful when using styles. They can save you time, but only if you know when to use them. Haphazard application of styles will eventually lead to frustration.
The difference in approach is that we don’t want to be thoughtful – I want to know the background color attribute for the sign-in button on the SignIn screen is in
sign-in-styles.xml under the
SignIn.SignInButton style. Consider a webpage – if you had a sign-in button with a distinct visual style to any other button on your website, would you define the visual style in CSS or on the HTML element?
The other nice (albeit rare) thing is that our designers can now fiddle with those files directly, while devs continue to work on functional aspects of the screen.
Can we take this approach further?
Yes, a hundred times yes. I’m glad you asked. In my next post, I’ll show you how color and dimension resources will be organised in Wutson, and the reasons why.