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.

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

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.


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!


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)
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.