Home > Android > Android Themes

Android Themes

A Note on Implementing Android Themes

This post contains geeky technical details regarding the implementation of a ‘light’ theme to Contact Lookup Pro and Fast.

You would think that implementing themes in Android would be straightforward, after all, there is a setTheme() method on an Activity.

However, it’s not as simple as that. Because of this, we’ve detailed the requirements here.

Background

We had a request from Ulrike to implement a ‘light’ theme instead of the default ‘dark’ theme we had used.

Being responsive to our customers and respecting choice, we thought it was a good idea. The use-case we decided on was that the user could change the theme dynamically via a menu option; a toggle theme option.

The Analysis

Android uses styles to define attributes to UI components. Styles can be referenced as a theme. Android defines two themes, Dark, the default, and Light.

Themes are applied to an Activity and this cascades the styles to all UI components in that activity. The activity class has a method to set the theme called, intuitively, setTheme(…).

How Hard Can it be? (aka Oww it Hurts to Continually Bang Your Head Against a Wall.)

Development is, in it’s purest form, simply the wiring together of components into a framework that does stuff. The wiring takes the form of code that tells the application how these components interact, using the component interfaces. If you understand the lingo and the component interfaces, it should all be straightforward.

However, as developers, we frequently come across things that suggest a particular mode of usage, but in reality are not as straightforward as the interface would suggest. It’s these things that cause developers problems. It’s these things that turn development from being something anyone can do into an activity that is suited only to engineers; people who can look beyond the code to identify the problems beyond the wiring.

As we found out, simple calling setTheme in an Android program is not enough. There’s a particular sequence and order of actions required to access the magic of this innocuous method call.

There’s Magic, and there’s Magic

Unfortunately, what should be straightforward turns into an exercise of faith. What we mean by this is there’s a particular sequence of steps that must be followed to get the simple setTheme() method to work. These steps are only found in the deepest recesses of StackOverflow and Google Groups. It annoyed us so much that we decided to document the secret here. And even this secret may not work in on all flavours of Android, as fragmentation is a real problem in cases like this.

Here are the secrets:

  • You must set the theme before the Activity loads the content view.
  • Not only that, you must call this before you call the activities super class. This step is necessary for any pre-3.0 OS device.
  • To dynamically change the theme you must start a new activity. The setTheme() method does nothing to the current activity if it has already loaded the content view.

The Code

Here’s how your Activities onCreate method should look:


public void onCreate(Bundle savedInstanceState) {

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);

// Get the theme
isThemeLight = sp.getBoolean("theme_is_light", false);

setTheme(isThemeLight ? android.R.style.Theme_Light : android.R.style.Theme_Black);

super.onCreate(savedInstanceState);
...
setContentView(R.layout.contact_search_list);
...

Note that we a reading the selected theme from the Android preferences. Furthermore, we do all of this before we call the super class.

To change the theme dynamically, we must start a new Activity. Here’s the code to do that:


if (!isPre20) {
overridePendingTransition(0, 0);
}

intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();

if (!isPre20) {
overridePendingTransition(0, 0);
}

startActivity(intent);

The overridePendingTransition() method call disables animations between the closing and opening activities. However, this is only available to Android OS 2.0 and above.

Note also the magic in starting the same activity, you must call finish() before calling the startActivity().

The Moral of this Story

Never, ever, do what the customer suggests ;-)

Light Theme

About these ads
Categories: Android Tags: ,
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: