Alterar o tema da atividade de maneira programática

121

Em casos específicos, preciso remover o tema da caixa de diálogo da minha atividade, mas não parece estar funcionando. Aqui está um exemplo

Primeira atividade:

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

Segunda atividade:

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

Trecho do manifesto:

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

Quando eu executo, ele ainda tem o tema de diálogo.

API10

Obrigado.

user1462299
fonte

Respostas:

183

Como os documentos dizem, você deve chamar setThemeantes de qualquer saída de visualização. Parece que super.onCreate()participa do viewprocessamento.

Portanto, para alternar entre os temas dinamicamente, você simplesmente precisa chamar setThemeantes super.onCreatedesta forma:

public void onCreate(Bundle savedInstanceState) {
    setTheme(android.R.style.Theme);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
}
user1462299
fonte
Funciona para mim no MotoG (v1) com pilha Android 5.1. Se não estiver funcionando para você, compartilhe o dispositivo + versão do Android.
lenrok258 de
Tive que definir um tema conforme descrito aqui: stackoverflow.com/a/44236460/3211335 E, em seguida, defini-lo conforme descrito por esta resposta. Funciona muito bem.
LaloLoop
Existe uma maneira que poderíamos definir tema apenas uma vez ... em vez de tema definido por página
gayan1991
Eu uso a preferência compartilhada para salvar o tema, mas ao reiniciar o aplicativo, por um momento o primeiro tema aparece e depois o segundo tema mostrado!
Mohammad Afrashteh
1
@ gayan1991 Você pode usar uma outra atividade para definir seu tema e fazer com que todas as outras atividades estendam esta ex: pastebin.com/r93qrRDG edit: use pastebin para ter uma formatação melhor
SocialSupaCrew
46

A resposta do user1462299 funciona muito bem, mas se você incluir fragmentos , eles usarão o tema de atividades original. Para aplicar o tema a todos os fragmentos também, você pode substituir o método getTheme () do Contexto:

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

Você não precisa mais chamar setTheme () no Método onCreate (). Você está substituindo todas as solicitações para obter o tema atual neste contexto desta forma.

Björn Kechel
fonte
2
@ quem votou negativamente: gostaria de explicar o que você não gosta em minha resposta?
Björn Kechel
O getTheme () deve ser substituído na Activity ou nos respectivos Fragments? Eu implementei isso na atividade, mas os fragmentos ainda estão usando o tema original da atividade.
saltandpepper
@saltandpepper Substituí-lo na Activity é o suficiente. Certifique-se de que seu código de fragmento e layout não os alterem novamente.
Björn Kechel
Isso não funcionou para mim, mas a resposta fornecida em stackoverflow.com/a/15496425/494179 sim.
saltandpepper de
2
Bom ponto user1269737, então você deve se certificar de que não há cálculos pesados. O simples retorno de um estilo em um caso de condição simples não afetará o desempenho.
Björn Kechel
12

Sei que estou atrasado, mas gostaria de postar uma solução aqui:
Verifique o código-fonte completo aqui .
Este é o código que usei ao alterar o tema usando as preferências.

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

}

Observe que você deve colocar o código antes de setcontentview ..

CODIFICAÇÃO FELIZ!

Dondondon
fonte
porque? a resposta é correta ?!
dondondon,
Eu uso a preferência compartilhada para salvar o tema, mas ao reiniciar o aplicativo, por um momento o primeiro tema aparece e depois o segundo tema mostrado!
Mohammad Afrashteh
0

Este funciona bem para mim:

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
fonte