Android Holo themes with backwards compatibility


The Android platform provides  a nice feature for app developers called themes. Themes allow developers to change the appearance of activities or the whole application easily. Developers can choose from themes like full-screen or no title bar, as well as ones that change the application from a dark to a light appearance. When Google introduced Android Honeycomb ( Version 3.X ) they also introduced a new theme family called Holo. This created a problem for app developers, if they target the new Holo theme in an application it will crash on older versions of Android. This may not seem like an issue but if we are using the old themes on new devices the application won’t look correct. For example:

Lets take a look at an example of the problem and then I’ll explain an easy fix. I have an existing activity that is using the no title bar theme:
1
2
3
4
5
<activity
android:name="com.example.main"
    android:theme="@android:style/Theme.NoTitleBar"
    android:label="@string/app_name"
    />
I can’t simply change to the new holo theme as follows because it will break compatibilty with 1.X and 2.X phones:
1
2
3
4
5
<activity
    android:name="com.example.main"
    android:theme="@android:style/Theme.Holo.NoActionBar"
    android:label="@string/app_name"
    />
Luckily there is an easy solution to this problem! We just need to create our own themes that inherit from the standard android ones. We can then place the files into folders using resource qualifiers to make sure the correct theme gets applied on the correct device.
Your application will already have a values folder in its res directory, we can add a new one called values-v11. If you know about version qualifiers already feel free to skip ahead, otherwise I’ll quickly explain them here. We can qualify the items in a resource folder by adding qualifiers. These can be based on the android platform version, the screen density or many other options. For this example we need to apply different styles for devices running android versions 1.X and 2.X and devices running 3.X and 4.X. When using resource qualifiers you have to use the platform version. You can look them up here. The qualifiers work on a best-match system that is beyond the scope of this post but any version greater than 11 will use our new values-v11 folder. You should end up with something that looks like this:

You will need to start by creating a themes.xml file in the values folder and add the following text:
1
2
3
4
5
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="Theme.Default" parent="@android:style/Theme"></style>
    <style name="Theme.NoTitle" parent="@android:style/Theme.NoTitleBar"></style>
    <style name="Theme.FullScreen" parent="@android:style/Theme.NoTitleBar.Fullscreen"></style>
</resources>
What we have done here is created three custom themes called Theme.Default, Theme.NoTitle and Theme.FullScreen and used the standard android themes as the parents. Now you can create a new themes.xml or copy this one into the values-v11 folder you created earlier. Edit it as follows:
1
2
3
4
5
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="Theme.Default" parent="@android:style/Theme.Holo"></style>
    <style name="Theme.NoTitle" parent="@android:style/Theme.Holo.NoActionBar"></style>
    <style name="Theme.FullScreen" parent="@android:style/Theme.Holo.NoActionBar.Fullscreen"></style>
</resources>
Now we need to go back to our application manifest and update the activities theme to one of our new custom ones:
1
2
3
4
5
<activity
    android:name="com.example.main"
    android:theme="@style/Theme.NoTitle"
    android:label="@string/app_name"
    />
We’re all done. If the user is using an older version of android they will get the old no title bar theme and if they are using a new one they will see the new Holo theme. You may think this doesn’t really matter but if you set the theme to NoTitleBar and the user is running the app on a new device the will see dialogs from the older android versions. This can confuse users because its not what they are used to seeing, or leave them wondering why your app doesn’t work properly on their phone.
Feel free to post any questions below and make sure you use the right themes!!

Comments

Popular posts from this blog

How to draw an overlay on a SurfaceView used by Camera on Android?

Create EditText with dropdown in android

Android TCP Connection Chat application