web-dev-qa-db-fra.com

Comment modifier le thème actuel à l'exécution dans Android

J'ai créé une PreferenceActivity qui permet à l'utilisateur de choisir le thème qu'il souhaite appliquer à l'ensemble de l'application.

Lorsque l'utilisateur sélectionne un thème, ce code est exécuté:

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

Mais, même si j'ai vérifié avec le débogueur que le code est en cours d'exécution, je ne vois aucun changement dans l'interface utilisateur.

Les thèmes sont définis dans res/values/styles.xml, et Eclipse ne montre aucune erreur.

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

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

Une idée de ce qui pourrait se passer et comment y remédier? Dois-je appeler setTheme à un moment particulier du code? Mon application comprend plusieurs activités si cela peut aider.

140
Guido

Je voudrais voir la méthode aussi, où vous définissez une fois pour toutes vos activités. Mais pour autant que je sache, vous devez définir chaque activité avant d'afficher un point de vue.

Pour référence vérifier ceci:

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

Edit (copié de ce 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);
}
84
Pentium10

Si vous souhaitez modifier le thème d'une activité existante, appelez recreate() après setTheme() .

Remarque: n'appelez pas recréer si vous changez de thème dans onCreate(), afin d'éviter une boucle infinie.

57
TPReal

recreate() (comme indiqué par TPReal ) ne fera que redémarrer l'activité en cours, mais les activités précédentes seront toujours dans la pile arrière et le thème ne leur sera pas appliqué.

Une autre solution à ce problème consiste donc à recréer complètement la pile de tâches, comme suit:

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

MODIFIER:

Il suffit de mettre le code ci-dessus après avoir changé de thème sur l'interface utilisateur ou ailleurs. Toutes vos activités doivent avoir la méthode setTheme() appelée avant onCreate(), probablement dans une activité parent. Il est également normal de stocker le thème choisi dans SharedPreferences, de le lire puis de le définir à l’aide de la méthode setTheme().

21
Yuriy Yunikov

j'ai eu le même problème mais j'ai trouvé la 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);
    }
}
17
Unknown

J'ai eu un problème similaire et j'ai résolu de cette façon ..

@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

}

ce code sert à recréer le paquet d'économie d'activité et à changer le thème. Vous devez écrire votre propre onSaveInstanceState (Bundle outState); Depuis API-11, vous pouvez utiliser la méthode recreate () à la place.

Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
9
Francesco Ditrani

Nous devons définir le thème avant d’appeler 'super.onCreate ()' et Méthode 'setContentView ()' .

Découvrez ce lien pour appliquer un nouveau thème à l'ensemble de l'application au moment de l'exécution.

9
Lalit Sharma

Au lieu de

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

utilisation

setTheme(R.style.BlackTheme);

Mon code: dans la méthode onCreate ():

super.onCreate(savedInstanceState);

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

setContentView(R.layout.activity_some_layout);

Quelque part (par exemple, sur un clic de bouton):

YourActivity.this.recreate();

Vous devez recréer l'activité, sinon - le changement ne se produira pas

4
Vitaly Zinchenko

Je sais que je suis en retard mais je voudrais poster une solution ici: Vérifiez le code source complet ici . C’est le code que j’ai utilisé lors du changement de thème en utilisant les préférences.

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);
}
2
dondondon

De cette façon, travaillez pour moi:

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

    setContentView(R.layout.activity_main);
}

Ensuite, vous voulez changer un nouveau thème:

GApplication.getInstance().setTheme(R.style.LightTheme);
recreate();
2
duongnx

C'est ce que j'ai créé pour Material Design. Puisse cela vous aider.

Jetez un oeil à MultipleThemeMaterialDesign

2

Vous pouvez terminer l'activité et la recréer par la suite. Ainsi, votre activité sera recréée et toutes les vues seront créées avec le nouveau thème.

1
Sumit Dhaniya

Appelez SetContentView (Resource.Layout.Main) après setTheme ().

0

Cela n'a eu aucun effet pour moi:

public void changeTheme(int newTheme) {
    setTheme(newTheme);
    recreate();
}

Mais cela a fonctionné:

int theme = R.style.default;

protected void onCreate(Bundle savedInstanceState) {
    setTheme(this.theme);
    super.onCreate(savedInstanceState);
}

public void changeTheme(int newTheme) {
    this.theme = newTheme;
    recreate();
}
0
arlomedia