Programowo zmieniaj motyw działania

121

W szczególnych przypadkach muszę usunąć motyw okna dialogowego z mojej aktywności, ale wydaje się, że nie działa. Oto przykład

Pierwsza czynność:

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

Druga czynność:

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

Manifest wyciąg:

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

Kiedy uruchamiam, nadal jest to okno dialogowe.

API10

Dzięki.

user1462299
źródło

Odpowiedzi:

183

Jak mówią doktorzy , musisz zadzwonić setThemeprzed jakimkolwiek wyjściem widoku. Wydaje się, że super.onCreate()bierze udział w viewprzetwarzaniu.

Tak więc, aby dynamicznie przełączać się między motywami, wystarczy zadzwonić setThemewcześniej super.onCreate:

public void onCreate(Bundle savedInstanceState) {
    setTheme(android.R.style.Theme);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
}
user1462299
źródło
Działa dla mnie na MotoG (v1) ze stosem Androida 5.1. Jeśli to nie działa, udostępnij urządzenie + wersję Androida.
lenrok258
Musiałem zdefiniować motyw zgodnie z opisem tutaj: stackoverflow.com/a/44236460/3211335 A następnie ustawić go zgodnie z opisem w tej odpowiedzi. Działa świetnie.
LaloLoop
Czy w ogóle możemy ustawić motyw tylko raz ... zamiast ustawiać motyw na stronę
gayan1991
Używam wspólnych preferencji, aby zapisać motyw, ale po ponownym uruchomieniu aplikacji przez chwilę pojawia się pierwszy motyw, a następnie pojawia się drugi motyw!
Mohammad Afrashteh
1
@ gayan1991 Możesz użyć innego działania, aby zdefiniować swój motyw i rozszerzyć wszystkie inne działania, np .: pastebin.com/r93qrRDG edit: użyj pastebin, aby uzyskać lepsze formatowanie
SocialSupaCrew
46

Odpowiedź użytkownika1462299 działa świetnie, ale jeśli dołączysz fragmenty , użyją oryginalnego motywu działań. Aby zastosować motyw również do wszystkich fragmentów, możesz zamiast tego nadpisać metodę getTheme () 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;
}

Nie ma już potrzeby wywoływania setTheme () w metodzie onCreate (). W ten sposób nadpisujesz każde żądanie uzyskania aktualnego motywu w tym kontekście.

Björn Kechel
źródło
2
@ ktokolwiek zlekceważył: czy możesz wyjaśnić, co ci się nie podoba w mojej odpowiedzi?
Björn Kechel
Czy metoda getTheme () powinna zostać zastąpiona w działaniu, czy w odpowiednich fragmentach? Zaimplementowałem to w działaniu, ale fragmenty nadal używają oryginalnego motywu działania.
saltandpepper
@saltandpepper Zastępowanie go w działaniu wystarczy. Upewnij się, że kod fragmentu i układ nie zmieniają go ponownie.
Björn Kechel
To nie zadziałało, ale odpowiedź podana na stackoverflow.com/a/15496425/494179 tak.
sól i pieprz
2
Dobry punkt użytkownika1269737, więc powinieneś upewnić się, że nie ma ciężkich obliczeń. Zwrócenie stylu w prostym przypadku warunku nie wpłynie na wydajność.
Björn Kechel
12

Wiem, że jestem późno, ale chciałbym, aby umieścić tu rozwiązanie:
Sprawdź pełny kod źródłowy tutaj .
To jest kod, którego użyłem podczas zmiany motywu za pomocą preferencji.

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

}

Pamiętaj, że musisz umieścić kod przed setcontentview ..

SZCZĘŚLIWEGO KODOWANIA!

dondondon
źródło
czemu? odpowiedź jest poprawna ?!
dondondon,
Używam wspólnych preferencji, aby zapisać motyw, ale po ponownym uruchomieniu aplikacji przez chwilę pojawia się pierwszy motyw, a następnie pojawia się drugi motyw!
Mohammad Afrashteh
0

Ten działa dobrze dla mnie:

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

Stosowanie:

  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
źródło