In this post we will talk about supporting multiple themes in Android application.

demo_two_themes

We will create demo application with 2 themes. User can choose of of this theme for whole application. Theme in our application will be change background color, status bar color,…

This image show different style tags and meaning for Android 5.+.
Firstly need to add dependency for build.grade file in our project.

dependencies {
    compile 'com.android.support:appcompat-v7:25.2.0'
}

For support changing background theme for Android version less 5 we can add own attribute called “backgroundColor” for it need to add file attrs.xml┬áto /res/values.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="backgroundColor" format="color"/>
</resources>

Next step is create different themes. For it we can use styles.xml or themes.xml files. In this case I used to steles.xml file.

<resources>
    <style name="AppTheme.Blue" parent="Theme.AppCompat">
        <item name="colorPrimary">@color/primaryColor_blue</item>
        <item name="colorPrimaryDark">@color/primaryColorDark_blue</item>
        <item name="colorAccent">@color/primaryAccent_blue</item>
        <item name="backgroundColor">@color/primaryColorDark_blue</item>
    </style>
    <style name="AppTheme.Red" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/primaryColor_red</item>
        <item name="colorPrimaryDark">@color/primaryColorDark_red</item>
        <item name="colorAccent">@color/primaryAccent_red</item>
        <item name="backgroundColor">@color/primaryColorDark_red</item>
    </style>
</resources>

After it need to add all colors to colors.xml file (/res/values/).

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="primaryColor_blue">#2196F3</color>
    <color name="primaryColorDark_blue">#1976D2</color>
    <color name="primaryAccent_blue">#E3F2FD</color>

    <color name="primaryColor_red">#F44336</color>
    <color name="primaryColorDark_red">#D32F2F</color>
    <color name="primaryAccent_red">#FFEBEE</color>
</resources>

Next step is update layout for MainActivity. In my case it’s a activity_main.xml (/res/layout/).

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="12dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"
    android:background="?attr/backgroundColor">
    <Button
        android:id="@+id/blue_theme_btn"
        android:text="BLUE"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/red_theme_btn"
        android:text="RED"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

When we used tag android:background=”?attr/backgroundColor” it’s our own tag, which we created in attrs.xml file. This tag depends of theme which active right now.

Our theme must saved after close app. For we will use SharedPreferences. I created class called Utility.java which contain next code.

public class Utility {

    public static void setTheme(Context context, int theme) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        prefs.edit().putInt(context.getString(R.string.prefs_theme_key), theme).apply();
    }

    public static int getTheme(Context context) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        return prefs.getInt(context.getString(R.string.prefs_theme_key), -1);
    }
}

For correct work this class need to add string constant to strings.xml file (/res/values/).

<resources>
    <string name="app_name">MultipleThemesApp</string>

    <string name="prefs_theme_key">theme</string>
</resources>

We can check and update theme in our MainActivity, but better way is create BaseActivity, which will check and init our theme for activity.

public class BaseActivity extends AppCompatActivity {

    private final static int THEME_BLUE = 1;
    private final static int THEME_RED = 2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        updateTheme();
    }
    public void updateTheme() {
        if (Utility.getTheme(getApplicationContext()) <= THEME_BLUE) {
            setTheme(R.style.AppTheme_Blue);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                getWindow().setStatusBarColor(getResources().getColor(R.color.primaryColorDark_blue));
            }
        } else if (Utility.getTheme(getApplicationContext()) == THEME_RED) {
            setTheme(R.style.AppTheme_Red);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                getWindow().setStatusBarColor(getResources().getColor(R.color.primaryColorDark_red));
            }
        }
    }
}

We must extend Main Activity from BaseActivity and add listeners to click button for change theme and recreate activity.

public class MainActivity extends BaseActivity implements View.OnClickListener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ((Button)findViewById(R.id.blue_theme_btn)).setOnClickListener(this);
        ((Button)findViewById(R.id.red_theme_btn)).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.blue_theme_btn:
                Utility.setTheme(getApplicationContext(), 1);
                recreateActivity();
                break;
            case R.id.red_theme_btn:
                Utility.setTheme(getApplicationContext(), 2);
                recreateActivity();
                break;
        }
    }

    public void recreateActivity() {
        Intent intent = getIntent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        finish();
        overridePendingTransition(0, 0);
        startActivity(intent);
        overridePendingTransition(0, 0);
    }
}

Last step is update AndroidManifest.xml with new default theme:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.alexzh.multiplethemesapp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme.Blue" >
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Full source code you can find here.

13 CommentsClose Comments

13 Comments

  • babagouda
    Posted January 17, 2017 at 12:05 pm 0Likes

    how can i download this code ..?

  • gillis haasnoot
    Posted March 14, 2017 at 12:50 am 0Likes

    Just as a side note.
    Applying a theme runtime will cause android to recursively apply and override style attributes. This is fine, but it consumes memory.
    I had quite some out of memory reports coming in from ancient devices.
    Another solution is to define multiple activities where:

    the default activity is just a loader activity. its checks which theme is stored in the sharedpreferences.
    Based on that info it loads either activityA or activityB
    ActivityB is identical to ActivityA (just an extension) With the difference that inside the manifest.xml you define the themes for both Activities.

    I know its not so elegant, but if you ever run into similar issues as what i have you can try this option.

  • rajkiran
    Posted June 21, 2017 at 5:28 am 0Likes

    how to change entire application theme…..your code is changing only current activity…if we go to another page/activity it is showing the default theme which we mentioned in manifest default theme

  • Posted June 21, 2017 at 6:06 am 0Likes

    Thank you for your comment. You should change theme for each activity use
    setTheme(R.style.THEME_NAME).

  • suha
    Posted December 19, 2017 at 8:44 am 0Likes

    could you please explain what and where to write in second activity to set the theme in all app

    • Posted January 16, 2018 at 7:05 pm 0Likes

      You have few options, first of all, you can set Theme for the whole app in Android:

      < application
          ...
          android:theme="@style/AppTheme.Blue" >
      

      You can set up the Theme for the Activity:

      < activity 
          android:name=".MainActivity"
          android:theme="@style/AppTheme.Blue ">
      

      And you can do it from the source code of Activity:

      @Override
      public void onCreate(Bundle savedInstanceState) {
          setTheme(R.style.AppTheme)
          super.onCreate(savedInstanceState)
          ...
      }
      
  • Nisha das
    Posted February 26, 2018 at 6:18 am 0Likes

    Thank you very much.The code is very easy to understand and useful

  • Neethu Pushpan
    Posted February 26, 2018 at 6:20 am 0Likes

    Thank you very much.The code is very easy to understand and useful. also very effective.

  • Robert
    Posted June 11, 2018 at 7:58 pm 0Likes

    Thank you for this simple example. One question though when using lighter colours for the appbar, the text is white and not very readable. How and where would I use primaryTextColor to change this. I have tried several ways and I cannot seem to get this aspect of the them to work correctly.

    • Posted June 20, 2018 at 7:03 pm 0Likes

      Hi Robert, thank you for your question. I don’t know what are you using during the development process. However, I recommend using the Toolbar. You can create a style for the Toolbar:

      %MINIFYHTMLd01c552c303da55d946eb7a4a588ffc935%

      After it, this style can be added to basic style:

      %MINIFYHTMLd01c552c303da55d946eb7a4a588ffc936%

Leave a comment