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 16:08

Instead of

getApplication().setTheme(R.style.BlackTheme);

use

setTheme(R.style.BlackTheme);

My code: in onCreate() method:

super.onCreate(savedInstanceState);

if(someExpression) {
    setTheme(R.style.OneTheme);
} else {
    setTheme(R.style.AnotherTheme);
}

setContentView(R.layout.activity_some_layout);

Somewhere (for example, on a button click):

YourActivity.this.recreate();

You have to recreate activity, otherwise - change won't happen

查看更多
笑指拈花
3楼-- · 2018-12-31 16:11

i got the same problem but i found the solution.

public class EditTextSmartPhoneActivity extends Activity implements DialogInterface.OnClickListener
{
    public final static int CREATE_DIALOG  = -1;
    public final static int THEME_HOLO_LIGHT  = 0;
    public final static int THEME_BLACK  = 1;

    int position;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        position = getIntent().getIntExtra("position", -1);

        switch(position)
        {
        case CREATE_DIALOG:
            createDialog();
            break;
        case THEME_HOLO_LIGHT:
            setTheme(android.R.style.Theme_Holo_Light);
            break;
        case THEME_BLACK:
            setTheme(android.R.style.Theme_Black);
            break;
        default:
        }

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

    }

    private void createDialog()
    {
        /** Options for user to select*/
        String choose[] = {"Theme_Holo_Light","Theme_Black"};

        AlertDialog.Builder b = new AlertDialog.Builder(this);

        /** Setting a title for the window */
        b.setTitle("Choose your Application Theme");

        /** Setting items to the alert dialog */
        b.setSingleChoiceItems(choose, 0, null);

        /** Setting a positive button and its listener */
        b.setPositiveButton("OK",this);

        /** Setting a positive button and its listener */
        b.setNegativeButton("Cancel", null);

        /** Creating the alert dialog window using the builder class */
        AlertDialog d = b.create();

        /** show dialog*/
        d.show();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        // TODO Auto-generated method stub
        AlertDialog alert = (AlertDialog)dialog;
        int position = alert.getListView().getCheckedItemPosition();

        finish();
        Intent intent = new Intent(this, EditTextSmartPhoneActivity.class);
        intent.putExtra("position", position);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
}
查看更多
梦该遗忘
4楼-- · 2018-12-31 16:12

I would like to see the method too, where you set once for all your activities. But as far I know you have to set in each activity before showing any views.

For reference check this:

http://www.anddev.org/applying_a_theme_to_your_application-t817.html

Edit (copied from that forum):

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

    // Call setTheme before creation of any(!) View.
     setTheme(android.R.style.Theme_Dark);

    // ...
    setContentView(R.layout.main);
}
查看更多
浮光初槿花落
5楼-- · 2018-12-31 16:16

I had a similar problem and I solved in this way..

@Override
public void onCreate(Bundle savedInstanceState) {

    if (getIntent().hasExtra("bundle") && savedInstanceState==null){
        savedInstanceState = getIntent().getExtras().getBundle("bundle");
    }

    //add code for theme

    switch(theme)
    {
    case LIGHT:
        setTheme(R.style.LightTheme);
        break;
    case BLACK:
        setTheme(R.style.BlackTheme);
        break;

    default:
    }
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //code

}

this code is for recreate the Activity saving Bundle and changing the theme. You have to write your own onSaveInstanceState(Bundle outState); From API-11 you can use the method recreate() instead

Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
查看更多
千与千寻千般痛.
6楼-- · 2018-12-31 16:16

This way work for me:

  @Override
protected void onCreate(Bundle savedInstanceState) {
    setTheme(GApplication.getInstance().getTheme());
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
}

Then you want to change a new theme:

GApplication.getInstance().setTheme(R.style.LightTheme);
recreate();
查看更多
查无此人
7楼-- · 2018-12-31 16:16

Call SetContentView(Resource.Layout.Main) after setTheme().

查看更多
登录 后发表回答