Modifica il tema dell'attività a livello di programmazione


121

In casi particolari ho bisogno di rimuovere il tema della finestra di dialogo dalla mia attività ma sembra che non funzioni. Ecco un esempio

Prima attività:

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

Seconda attività:

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

Estratto del manifesto:

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

Quando corro è ancora a tema dialoghi.

API10

Grazie.

Risposte:


183

Come dicono i documenti, devi chiamare setThemeprima di qualsiasi output di visualizzazione. Sembra che super.onCreate()prenda parte viewall'elaborazione.

Quindi, per passare da un tema all'altro in modo dinamico, devi semplicemente chiamare setThemeprima in super.onCreatequesto modo:

public void onCreate(Bundle savedInstanceState) {
    setTheme(android.R.style.Theme);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
}

Funziona per me su MotoG (v1) con stack Android 5.1. Se non funziona per te, condividi il dispositivo + la versione Android.
lenrok258

Ho dovuto definire un tema come descritto qui: stackoverflow.com/a/44236460/3211335 E poi impostarlo come descritto da questa risposta. Funziona benissimo.
LaloLoop

Possiamo comunque impostare il tema solo una volta ... invece di impostare il tema per pagina
gayan1991

Uso la preferenza condivisa per salvare il tema, ma quando riavvio l'app, per un momento appare il primo tema, quindi viene mostrato il secondo tema!
Mohammad Afrashteh

1
@ gayan1991 Puoi usare un'altra attività per definire il tuo tema e fare in modo che tutte le tue altre attività estendano questo ex: pastebin.com/r93qrRDG modifica: usa pastebin per avere una formattazione migliore
SocialSupaCrew

46

La risposta di user1462299 funziona alla grande, ma se includi frammenti , useranno il tema delle attività originali. Per applicare il tema anche a tutti i frammenti, puoi invece sostituire il metodo getTheme () del Context:

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

Non è più necessario chiamare setTheme () nel metodo onCreate (). Stai annullando ogni richiesta per ottenere il tema corrente in questo contesto in questo modo.


2
@ chi ha votato negativamente: ti interessa spiegare cosa non ti piace della mia risposta?
Björn Kechel

GetTheme () dovrebbe essere sovrascritto nell'attività o nei rispettivi frammenti? L'ho implementato nell'attività, ma i frammenti utilizzano ancora il tema dell'attività originale.
saltandpepper

@saltandpepper È sufficiente sovrascriverlo nell'attività. Assicurati che il codice e il layout del frammento non lo cambino di nuovo.
Björn Kechel

Questo non ha funzionato per me, ma la risposta fornita in stackoverflow.com/a/15496425/494179 sì .
saltandpepper

2
Buon punto user1269737 quindi dovresti assicurarti che non ci siano calcoli pesanti. La semplice restituzione di uno stile all'interno di una semplice condizione non influirà sulle prestazioni.
Björn Kechel

12

So di essere in ritardo ma vorrei pubblicare una soluzione qui:
controlla il codice sorgente completo qui .
Questo è il codice che ho usato quando ho cambiato tema usando le preferenze.

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

}

Tieni presente che devi inserire il codice prima di setcontentview ..

CODIFICA FELICE!


perché? la risposta è corretta ?!
dondondon

Uso la preferenza condivisa per salvare il tema, ma quando riavvio l'app, per un momento appare il primo tema, quindi viene mostrato il secondo tema!
Mohammad Afrashteh

0

Questo funziona bene per me:

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)
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.