Cambiar el tema de la actividad mediante programación

121

En casos particulares, necesito eliminar el tema del diálogo de mi actividad, pero parece que no funciona. Aquí hay un ejemplo

Primera actividad:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    startActivity(new Intent(MainActivity.this, SecondActivity.class));
}

Segunda actividad:

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setTheme(android.R.style.Theme);
    setContentView(R.layout.activity_second);
}

Extracto manifiesto:

 <activity android:name="SecondActivity" android:theme="@android:style/Theme.Dialog"></activity>

Cuando ejecuto, sigue siendo un tema de diálogo.

API10

Gracias.

usuario1462299
fuente

Respuestas:

183

Como dicen los documentos , debe llamar setThemeantes de cualquier salida de vista. Parece que super.onCreate()participa en el viewprocesamiento.

Entonces, para cambiar entre temas dinámicamente, simplemente necesita llamar setThemeantes de super.onCreateesta manera:

public void onCreate(Bundle savedInstanceState) {
    setTheme(android.R.style.Theme);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
}
usuario1462299
fuente
Me funciona en MotoG (v1) con pila Android 5.1. Si no funciona para usted, comparta el dispositivo + la versión de Android.
lenrok258
Tuve que definir un tema como se describe aquí: stackoverflow.com/a/44236460/3211335 Y luego configurarlo como se describe en esta respuesta. Funciona muy bien.
LaloLoop
De todos modos, podríamos establecer el tema solo una vez ... en lugar de establecer el tema por página
gayan1991
Utilizo la preferencia compartida para guardar el tema, pero al reiniciar la aplicación, ¡por un momento aparece el primer tema y luego se muestra el segundo!
Mohammad Afrashteh
1
@ gayan1991 Puede usar otra actividad para definir su tema y hacer que todas sus otras actividades extiendan esta, por ejemplo: pastebin.com/r93qrRDG edit: use pastebin para tener un mejor formato
SocialSupaCrew
46

La respuesta de user1462299 funciona muy bien, pero si incluye fragmentos , usarán el tema de actividades original. Para aplicar el tema a todos los fragmentos también, puede anular el método getTheme () del contexto en su lugar:

@Override
public Resources.Theme getTheme() {
    Resources.Theme theme = super.getTheme();
    if(useAlternativeTheme){
        theme.applyStyle(R.style.AlternativeTheme, true);
    }
    // you could also use a switch if you have many themes that could apply
    return theme;
}

Ya no es necesario llamar a setTheme () en el método onCreate (). Está anulando todas las solicitudes para obtener el tema actual dentro de este contexto de esta manera.

Björn Kechel
fuente
2
@ quien haya votado negativamente: ¿te importaría explicar lo que no te gusta de mi respuesta?
Björn Kechel
¿Se debe anular getTheme () en la Actividad o en los Fragmentos respectivos? Implementé esto en la Actividad, pero los Fragmentos todavía usan el tema de Actividad original.
saltandpepper
@saltandpepper Anularlo en la Actividad es suficiente. Asegúrese de que el código de fragmento y el diseño no lo vuelvan a cambiar.
Björn Kechel
Esto no funcionó para mí, pero la respuesta proporcionada en stackoverflow.com/a/15496425/494179 sí lo hizo.
saltandpepper
2
Buen punto user1269737 por lo que debe asegurarse de que no haya cálculos pesados. Simplemente devolver un estilo dentro de un caso de condición simple no afectará el rendimiento.
Björn Kechel
12

Sé que llego tarde, pero me gustaría publicar una solución aquí:
consulte el código fuente completo aquí .
Este es el código que usé al cambiar el tema usando 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);

}

Tenga en cuenta que debe poner el código antes de setcontentview ..

¡FELIZ CODIFICACIÓN!

dondondon
fuente
¿por qué? ¡¿La respuesta es correcta ?!
dondondon
Utilizo la preferencia compartida para guardar el tema, pero al reiniciar la aplicación, ¡por un momento aparece el primer tema y luego se muestra el segundo!
Mohammad Afrashteh
0

Este funciona bien para mí:

theme.applyStyle(R.style.AppTheme, true)

Uso:

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //The call goes right after super.onCreate() and before setContentView()
    theme.applyStyle(R.style.AppTheme, true)
    setContentView(layoutId)
    onViewCreated(savedInstanceState)
}
Tamim Attafi
fuente