How to change current Theme at runtime in Android

2018-12-31 15:30发布

This question already has an answer here:

I've created a PreferenceActivity that allows the user to choose the theme he wants to apply to the entire application.

When the user selects a theme, this code is executed:

if (...) {
    getApplication().setTheme(R.style.BlackTheme);
} else {
    getApplication().setTheme(R.style.LightTheme);
}

But, even though I've checked with the debugger that the code is being executed, I can't see any change in the user interface.

Themes are defined in res/values/styles.xml, and Eclipse does not show any error.

<resources>
    <style name="LightTheme" parent="@android:style/Theme.Light">
    </style>

    <style name="BlackTheme" parent="@android:style/Theme.Black">
    </style>    
</resources>

Any idea about what could be happening and how to fix it? Should I call setTheme at any special point in the code? My application consists of several Activities if that helps.

13条回答
爱死公子算了
2楼-- · 2018-12-31 15:52

recreate() (as mentioned by TPReal) will only restart current activity, but the previous activities will still be in back stack and theme will not be applied to them.

So, another solution for this problem is to recreate the task stack completely, like this:

    TaskStackBuilder.create(getActivity())
            .addNextIntent(new Intent(getActivity(), MainActivity.class))
            .addNextIntent(getActivity().getIntent())
            .startActivities();

EDIT:

Just put the code above after you perform changing of theme on the UI or somewhere else. All your activities should have method setTheme() called before onCreate(), probably in some parent activity. It is also a normal approach to store the theme chosen in SharedPreferences, read it and then set using setTheme() method.

查看更多
几人难应
3楼-- · 2018-12-31 15:58

I know that i am late but i would like to post a solution here: Check the full source code here. This is the code i used when changing theme using preferences..

SharedPreferences pref = PreferenceManager
        .getDefaultSharedPreferences(this);
String themeName = pref.getString("prefSyncFrequency3", "Theme1");
if (themeName.equals("Africa")) {
    setTheme(R.style.AppTheme);
} else if (themeName.equals("Colorful Beach")) {
    //Toast.makeText(this, "set theme", Toast.LENGTH_SHORT).show();
    setTheme(R.style.beach);
} else if (themeName.equals("Abstract")) {
    //Toast.makeText(this, "set theme", Toast.LENGTH_SHORT).show();
    setTheme(R.style.abstract2);
} else if (themeName.equals("Default")) {
    setTheme(R.style.defaulttheme);
}
查看更多
查无此人
4楼-- · 2018-12-31 16:02

If you want to change theme of an already existing activity, call recreate() after setTheme().

Note: don't call recreate if you change theme in onCreate(), to avoid infinite loop.

查看更多
情到深处是孤独
5楼-- · 2018-12-31 16:03

We have to set theme before calling 'super.onCreate()' and 'setContentView()' method.

Check out this link for applying new theme to whole application at runtime.

查看更多
ら面具成の殇う
6楼-- · 2018-12-31 16:03

You can finish the Acivity and recreate it afterwards in this way your activity will be created again and all the views will be created with the new theme.

查看更多
听够珍惜
7楼-- · 2018-12-31 16:07

This is what i have created for Material Design. May it will helpful you.

Have a look for MultipleThemeMaterialDesign

查看更多
登录 后发表回答