0

I have made a simple app and i want to change the theme of all the activities of the app (including the settings activity) after selecting from the preference but the themes do not apply after selection. I've tried adding a recreate() but gets stuck in trying to start the main activity. For now, i added a menu item that does recreate() but i want it to apply automatically once you leave the settings activity.

MainActivity.java:

@Override
protected void onCreate(Bundle savedInstanceState) {

    SharedPreferences getData = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
    String themeValues = getData.getString("theme_preference", "1");

    if (themeValues.equals("1")) {
        setTheme(R.style.Theme_Light);
    }

    if (themeValues.equals("2")) {
        setTheme(R.style.Theme_Dark);
    }

    if (themeValues.equals("3")) {
        setTheme(R.style.Theme_Red);
    }

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
}

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (id == R.id.action_settings) {
            Intent i = new Intent("com.cyanoise.helloworld.SettingsActivity");
            startActivity(i);

        return true;
    }

    if (id == R.id.about_app) {
        startActivity(new Intent(MainActivity.this, AboutActivity.class));

        return true;
    }

    if (id == R.id.refresh_app) {
        recreate();

        return true;
    }

    if (id == R.id.exitapp) {
        finish();
    }

    return super.onOptionsItemSelected(item);
}

SettingsActivity.java:

public class SettingsActivity extends PreferenceActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        addPreferencesFromResource(R.xml.settings);
    }
}

All answers are greatly appreciated.

cyanoise
  • 1
  • 2
  • 6
  • possible duplicate of [How to change current Theme at runtime in Android](http://stackoverflow.com/questions/2482848/how-to-change-current-theme-at-runtime-in-android) – Phantômaxx Dec 01 '14 at 15:31
  • @DerGolem I've seen that post and I don't quite understand the code and answers there. Was hoping for a clearer and a little bit more explained answer here. – cyanoise Dec 02 '14 at 03:22
  • In synthesis, the theme won't be applied until **every Activity** is restarted. – Phantômaxx Dec 02 '14 at 07:59

2 Answers2

2

In order to apply a new theme in every activity when returning to it, but still only recreate activities when it is necessary, I am using a self-written BaseActivity, from which all my activities inherit.

In onCreate() the theme for each activity is set and saved in a String variable theme. By remembering the current theme of every activity you can compare it with your new theme from SharedPreferences in onResume() whenever the user turns to this activity.

Like this, you only need to call this.recreate() on resumed activities if the theme doesn't match yet, to make every activity show the up-to-date theme.

public abstract class BaseActivity extends AppCompatActivity {

   String theme;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        theme = PreferenceManager.getDefaultSharedPreferences(this).getString(getString(R.string.prefsThemesList), getString(R.string.prefsThemesList_default));
        try {
            Field resourceField = R.style.class.getDeclaredField(theme);
            int resourceId = resourceField.getInt(resourceField);
            setTheme(resourceId);
        } catch (Exception e) {
            e.printStackTrace();
        }

        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onResume() {
        super.onResume();
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        if (!theme.equals(prefs.getString(getString(R.string.prefsThemesList), " none "))) {
            this.recreate();
        }
    }
}
Quizzer
  • 21
  • 4
-1

Okay so I've been playing around and found a workaround to it. I added a onBackPressed() in the SettingsActivity to bring up the MainActivity again and it seemed to work, applying the selected theme once exiting the settings activity.

@Override
public void onBackPressed() {
    super.onBackPressed();
    startActivity(new Intent(SettingsActivity.this, MainActivity.class));
}

As for applying themes to all activities i just added

SharedPreferences getData = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
    String themeValues = getData.getString("theme_preference", "1");

    if (themeValues.equals("1")) {
        setTheme(R.style.Theme_Light);
    }

    if (themeValues.equals("2")) {
        setTheme(R.style.Theme_Dark);
    }

    if (themeValues.equals("3")) {
        setTheme(R.style.Theme_Red);
    }

to every onCreate of every activity.

cyanoise
  • 1
  • 2
  • 6
  • 4
    A cleaner way of doing this would be to create an abstract base activity, and extend all of your activities from this. You can then do your theme logic in the base class. – WoogieNoogie Dec 02 '14 at 04:36
  • 1
    A `switch` statement would be better than multiple `if` statements in terms of code readability. – Edric Jun 23 '18 at 15:48