Cómo cambiar el tema actual en tiempo de ejecución en Android

Creé una Actividad de preferencia que permite al usuario elegir el tema que quiere aplicar a toda la aplicación.

Cuando el usuario selecciona un tema, este código se ejecuta:

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

Pero, aunque he comprobado con el depurador que el código se está ejecutando, no puedo ver ningún cambio en la interfaz de usuario.

Los temas se definen en res/values/styles.xml , y Eclipse no muestra ningún error.

       

¿Alguna idea sobre lo que podría estar pasando y cómo solucionarlo? ¿Debería llamar a setTheme en algún punto especial del código? Mi aplicación consiste en varias actividades si eso ayuda.

Me gustaría ver el método también, donde estableces una vez para todas tus actividades. Pero hasta donde sé, debes establecer cada actividad antes de mostrar cualquier punto de vista.

Para referencia, verifique esto:

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

Editar (copiado de ese foro):

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

Si desea cambiar el tema de una actividad ya existente, llame a recreate() después de setTheme() .

Nota: no llame a recreate si cambia el tema en onCreate() , para evitar el bucle infinito.

recreate() (como lo menciona TPReal ) solo reiniciará la actividad actual, pero las actividades anteriores seguirán en la stack de respaldo y no se les aplicará el tema.

Entonces, otra solución para este problema es recrear completamente la stack de tareas, así:

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

EDITAR:

Simplemente coloque el código anterior después de realizar el cambio de tema en la interfaz de usuario o en otro lugar. Todas sus actividades deben tener el método setTheme() llamado before onCreate() , probablemente en alguna actividad principal. También es un método normal para almacenar el tema elegido en SharedPreferences , leerlo y luego establecerlo usando el método setTheme() .

Tengo el mismo problema, pero encontré la solución.

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

Tenemos que establecer el tema antes de llamar al método ‘super.onCreate ()’ y ‘setContentView ()’ .

Consulte este enlace para aplicar un nuevo tema a toda la aplicación en tiempo de ejecución.

Tuve un problema similar y lo resolví de esta manera …

 @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 } 

este código es para recrear el Paquete de ahorro de actividad y cambiar el tema. Tienes que escribir el tuyo enSaveInstanceState (Bundle outState); Desde API-11 puede usar el método recrear () en su lugar

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

Esto es lo que he creado para Material Design. Que te sea útil.

Eche un vistazo a MultipleThemeMaterialDesign

Sé que llego tarde pero me gustaría publicar una solución aquí: compruebe el código fuente completo aquí . Este es el código que utilicé cuando cambié el tema usando las preferencias.

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

En lugar de

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

utilizar

 setTheme(R.style.BlackTheme); 

Mi código: en el método onCreate ():

 super.onCreate(savedInstanceState); if(someExpression) { setTheme(R.style.OneTheme); } else { setTheme(R.style.AnotherTheme); } setContentView(R.layout.activity_some_layout); 

En algún lugar (por ejemplo, al hacer clic en un botón):

 YourActivity.this.recreate(); 

Tienes que recrear la actividad; de lo contrario, el cambio no sucederá

De esta manera me funciona:

  @Override protected void onCreate(Bundle savedInstanceState) { setTheme(GApplication.getInstance().getTheme()); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } 

Entonces quieres cambiar un nuevo tema:

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

Puede finalizar el Acivity y volver a crearlo de esta forma, de esta forma su actividad se creará nuevamente y todas las vistas se crearán con el nuevo tema.

Llame a SetContentView (Resource.Layout.Main) después de setTheme ().

Esto no tuvo ningún efecto para mí:

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

Pero esto funcionó:

 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(); }