A Time and Place for Styles

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.


screenshot of Wutson

The screen has two elements – a Toolbar and a RecyclerView:

<?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.

The 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.

trending-shows-styles.xml:

<?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:

wutson-styles.xml:

<?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, xyz-styles.xml
  • 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 ScreenNameSpace.ComponentName
  • 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.

from Dan Lew – Styling Views on Android (Without Going Crazy)

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>