November 25, 2014
Hot Topics:

Changing Your Android App's Theme Dynamically

  • April 8, 2013
  • By Jessica Thornsbury
  • Send Email »
  • More Articles »

In this tutorial, I'll provide a brief intro into the concept of themes in Android, before showing you how to put themes to work by creating a project where the user can change the app's theme dynamically at runtime, simply by clicking a button.

Intro to Themes

In Android, 'themes' are an easy way to apply consistent formatting to your user interface (UI.) Defining a theme in advance not only saves you coding time in the long run, but it means that if you ever need to make UI adjustments, you only need to touch the code in one location. This saves you time and reduces the chances of human error.

'Themes' and 'styles' are often used almost interchangeably in Android tutorials. For the sake of clarity, we'll focus on themes in this tutorial, but in reality the only difference between a theme and a style is their scope:

  • A theme is a set of formatting rules applied across entire activities or applications.
  • A style is a set of formatting rules applied to a View.

Creating a Custom Theme

The Android platform includes some pre-defined themes, but it's easy to create your own so we'll jump straight into defining a custom theme.

When you create an Android project, Eclipse automatically generates a 'styles.xml' file in the res/layout folder. You can define themes in 'styles.xml' or if you want to keep your themes and styles separate you can create a dedicated themes file. To create a 'themes.xml' file, right click and select 'New' followed by 'Android XML File.'

Whether you're working with 'themes.xml' or 'styles.xml,' custom themes are defined in the following steps:

1) Add the opening and closing 'resources' tags:

<resources>

</resources>

2) Give your theme a unique name, and add the closing 'style' tag:

<resources>

<style name="BlackTheme" >

</style>

</resources>

3) Define the visual aspects of your theme using pairs of XML attributes and values:

<item name="android:background">#000000</item>

In this tutorial, we'll create two themes that define different background colors and text colors:

<resources>
<style name="BlackTheme" >

<item name="android:background">#000000</item>

<item name="android:textColor">#FFFFFF</item>

</style>



<style name="BlueTheme" >

<item name="android:background">#B0E0E6</item>

<item name="android:textColor">#000000</item>

</style>



</resources>

Create Your Layout

To check that the theme switching functionality is working, we'll create a layout that highlights changes of text and background color. We'll also give the user a way of toggling between the themes and of course, let them know that the app has this option in the first place!

Open your layout file and enter the following:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical" >

<TextView

android:id="@+id/textView1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentTop="true"

android:layout_centerHorizontal="true"

android:layout_marginTop="14dp"

android:text="@string/pick"

android:textAppearance="?android:attr/textAppearanceLarge" />



<Button

android:id="@+id/blackbutton"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/textView1"

android:text="@string/black" />



<Button

android:id="@+id/bluebutton"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_alignRight="@+id/blackbutton"

android:layout_below="@+id/blackbutton"

android:text="@string/blue" />



<EditText

android:id="@+id/editText1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignLeft="@+id/textView2"

android:layout_below="@+id/bluebutton"

android:ems="10"

android:hint="Name"

android:inputType="textPersonName" >



</EditText>



<TextView

android:id="@+id/textView2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignRight="@+id/editText3"

android:layout_below="@+id/editText3"

android:text="@string/agree" />



<EditText

android:id="@+id/editText3"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/editText1"

android:ems="10"

android:hint="Password"

android:inputType="numberPassword" />

</RelativeLayout>

Define Your Strings

As you've probably already noticed, the layout references several strings. Open res/values/strings.xml and add the following:

<string name="black">Black</string>

<string name="blue">Blue</string>

<string name="pick">Pick Your Colour</string>

<string name="agree">I agree to the terms and conditions</string>

MainActivity.java

Now comes the tough bit: implementing the actual functionality! Open the MainActivity.java file in the src/package directory.

We'll go through the code in sections and highlight some of the most important points.

import android.os.Bundle;

import android.app.Activity;

import android.view.View;

import android.view.View.OnClickListener;

These are the import statements for the various classes and interfaces used in your app. The 'OnClickListener' is especially important as this allows a callback to be invoked when your buttons are clicked.

public class MainActivity extends Activity implements OnClickListener

{

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) 

{

super.onCreate(savedInstanceState);

themeUtils.onActivityCreateSetTheme(this);

setContentView(R.layout.activity_main);

Here, your Activity is implementing that all-important OnClickListener. For now, ignore the error Eclipse throws on themeUtils.onActivityCreateSetTheme

findViewById(R.id.blackbutton).setOnClickListener(this);

findViewById(R.id.bluebutton).setOnClickListener(this);

}

Tell the OnClickListener which views it should be "listening" to.

@Override

public void onClick(View v) 

{

switch (v.getId())

{

This is called when your view (i.e your button) is clicked.

case R.id.blackbutton:

themeUtils.changeToTheme(this, themeUtils.BLACK);

break;

case R.id.bluebutton:

themeUtils.changeToTheme(this, themeUtils.BLUE);

break;

}

}

}

It's impossible for a theme to be black and blue simultaneously, hence the break statements (if the button that's pressed is black, there's no need for your program to run through the blue button code.)

Note, this last section will throw plenty of errors, but in the next step we'll create the themeUtils class and these warnings will disappear.

Create themeUtils.java

The next step is to create the new class that we're referring to in MainActivity.java, and create some static methods to support our theme changing functionality. To create a new class, open the src/package directory. Right-click, open the 'New' menu and select the 'Class' option. Enter the name 'themeUtils.'

New Java Class 
New Java Class

Open the new file and enter the following:

package com.jessica.theme;



import android.app.Activity;

import android.content.Intent;


 public class themeUtils

{

private static int cTheme;



public final static int BLACK = 0;

public final static int BLUE = 1;

public static void changeToTheme(Activity activity, int theme)

{

cTheme = theme;

activity.finish();



activity.startActivity(new Intent(activity, activity.getClass()));


 }

public static void onActivityCreateSetTheme(Activity activity)

{

switch (cTheme)

{

default:

case BLACK:

activity.setTheme(R.style.BlackTheme);

break;

case BLUE:

activity.setTheme(R.style.BlueTheme);

break;

}

}

}

Check Your Work

All the errors created by the references to themeUtils.java should now have disappeared; (if they haven't, hit the 'Save' button to force Eclipse to recognize your changes.) Now it's time to boot up the emulator, or launch the app on an attached device, and take a look at your work.

Launch the app
Launch the app

Click the buttons to check the theme switching functionality works.

Check the theme switching functionality
Check the theme switching functionality

Moving On...

One of the major benefits of Java, is that there's no need to touch previously tested code when adding new functionality. If at this point you wanted to add an extra theme, you'd work your way through the different files and add a few lines of new code to each, for example:

1) Open res/layout/activity_main.xml and add:

<Button

android:id="@+id/pinkbutton"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/bluebutton"

android:text="@string/pink" />

2) Open res/values/strings.xml and add an extra string:

<string name="pink">Pink</string>

3) Define a new style in res/values/styles.xml:

<style name="PinkTheme" >

<item name="android:background">#FF1493</item>

<item name="android:textColor">#000000</item>

</style>

4) Open themeUtils.java and add two references to your new theme. The first:

public final static int BLACK = 0;

public final static int BLUE = 1;

public final static int PINK = 2;

And the second:

case BLACK:

activity.setTheme(R.style.BlackTheme);

break;

case BLUE:

activity.setTheme(R.style.BlueTheme);

break;

case PINK:

activity.setTheme(R.style.PinkTheme);

break;

}

}

}

5) Finally, open MainActivity.java and set an onClickListener on the new button:

 

findViewById(R.id.blackbutton).setOnClickListener(this);

findViewById(R.id.bluebutton).setOnClickListener(this);

findViewById(R.id.pinkbutton).setOnClickListener(this);

}

And one final addition:

case R.id.blackbutton:

themeUtils.changeToTheme(this, themeUtils.BLACK);

break;

case R.id.bluebutton:

themeUtils.changeToTheme(this, themeUtils.BLUE);

break;

case R.id.pinkbutton:

themeUtils.changeToTheme(this, themeUtils.PINK);

break;

}

}

}

 

6) Boot up the emulator or external device, and take a look at the difference a few lines of code can make:

The difference a few lines of code can make
The difference a few lines of code can make

About the Author:

Jessica Thornsby is a technical writer based in Sheffield. She spends her spare time editing the CD reviews section at www.leedsmusicscene.net, contributing to A Short Fanzine About Rocking, and researching her family tree.


Tags: open source, UI, Google, Android, smartphone, themes, app development




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel