Android: Toggling Your App's Theme

I was recently asked how an app's theme can be toggled by the user in Android. This is a nice feature that is often seen in reading apps.

I've always found Android's approach to theming overwhelmingly complex, but with the Android 5 Lollipop release and Design Support Library, Google have made great progress in simplifying things.

Recent builds of Android Studio have also included an early Theme Editor which can be used to edit and preview your app's themes and how it will affect various widgets.

In this tutorial, we'll build a simple app with a switch that lets the user toggle between dark and light themes.

Theme Toggling Screenshot

The full source code for this tutorial is available at https://github.com/cblunt/blog-android-theme-toggler.

$ git clone [email protected]:cblunt/blog-android-theme-toggler.git

Create the project

Note: For this project, I'm using the latest Android Studio 2.0 beta release (preview2).

We'll start by creating a new application:

Build the UI

Once generated, we'll add a switch widget for the user to toggle the app's theme:

<!-- res/layout/content_main.xml -->
<Switch
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Toggle Theme"
  android:id="@+id/switch1"
  android:layout_alignParentTop="true"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:layout_alignParentRight="true"
  android:layout_alignParentEnd="true" />

Next, we'll hook up our switch to toggle the application's theme:

// app/src/main/java/com/example/themetoggler/MainActivity.java
public class MainActivity extends AppCompatActivity {
  // ...
  protected void onCreate(Bundle savedInstanceState) {
    // ...
    Switch toggle = (Switch) findViewById(R.id.switch1);

    toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
      @Override
      public void onCheckedChanged(CompoundButton view, boolean isChecked) {
        toggleTheme(isChecked);
      }
    });
  }

Saving the User's Choice

When the theme is toggled, we'll need to restart the current Activity to use the chosen theme. This is similar to configuration changes in Android (e.g. screen rotation) where the system will destroy and recreate the current Activity.

We'll also need to store the user's chosen theme so the re-created Activity knows which theme to use. It makes sense to store this in the app's SharedPreferences so that the user's choice is persisted across application launches.

After storing the user's preference, we store a reference to the Activity's original Intent, finish the current activity and restart it using that original Intent:

// app/src/main/java/com/example/themetoggler/MainActivity.java
public class MainActivity extends AppCompatActivity {
  private static final String PREFS_NAME = "prefs";
  private static final String PREF_DARK_THEME = "dark_theme";

  // ...

  private void toggleTheme(boolean darkTheme) {
    SharedPreferences.Editor editor = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit();
    editor.putBoolean(PREF_DARK_THEME, darkTheme);
    editor.apply();

    Intent intent = getIntent();
    finish();

    startActivity(intent);
  }
}

Creating the Theme

Finally, we'll need to change the Activity's onCreate method to use the user's preferred theme.

However, we haven't created any alternative themes yet, so let's do that first.

Let's add an alternative AppTheme.Dark which extends the default Theme.AppCompat. We can use the original AppTheme that Android Studio created as the basis for our theme:

<!-- app/src/main/res/values/styles.xml -->
<style name="AppTheme.Dark" parent="Theme.AppCompat">
  <!-- Dark theme base colours -->
  <item name="colorPrimary">@color/darkColorPrimary</item>
  <item name="colorPrimaryDark">@color/darkColorPrimaryDark</item>
  <item name="colorAccent">@color/darkColorAccent</item>
</style>
<!-- app/src/main/res/values/styles.xml -->
<style name="AppTheme.Dark.NoActionBar">
  <item name="windowActionBar">false</item>
  <item name="windowNoTitle">true</item>
</style>

<style name="AppTheme.Dark.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.Dark.PopupOverlay" parent="ThemeOverlay.AppCompat" />
<!-- app/src/main/res/values/colors.xml -->
<color name="darkColorPrimary">#1e2756</color>
<color name="darkColorPrimaryDark">#141831</color>
<color name="darkColorAccent">#2aac4b</color>

We've now declared enough for our themes to be used in the app. You can use Android Studio's experimental Theme Editor to preview and tweak your themes:

Theme Editor Preview

Applying the theme

Finally, back in our code, we can instruct our Activity to use the selected theme in onCreate().

Note that the code must be at the top of onCreate() (before the call to super.onCreate()) so that the app's default theme (specified in AndroidManifest.xml) is overridden

// app/src/main/java/com/example/themetoggler/MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
  // Use the chosen theme
  SharedPreferences preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
  boolean useDarkTheme = preferences.getBoolean(PREF_DARK_THEME, false);

  if(useDarkTheme) {
    setTheme(R.style.AppTheme_Dark_NoActionBar);
  }

  super.onCreate(savedInstanceState);
  // ...
// app/src/main/java/com/example/themetoggler/MainActivity.java
Switch toggle = (Switch) findViewById(R.id.switch1);
toggle.setChecked(useDarkTheme);
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
// ...

Finally, run your app and tap the switch to toggle between your dark and light themes. With every toggle, the Activity will be restarted.


This tutorial introduces how you can give the user a choice of theme for your app. The code you added for applying theme (at the top of onCreate()) would be common across all the Activities in your app.

For this reason, it would be a good thing to extract into a BaseActivity from which all your app's Activities inherit.

I hope you've found this tutorial useful. Please let me know your thoughts and feedback in the comments below, or by getting in touch on Twitter (@cblunt).

Full Source Code: https://github.com/cblunt/blog-android-theme-toggler