Wie wechselt man Themen (Nachtmodus), ohne die Aktivität neu zu starten?

Lesezeit: 7 Minuten

Benutzer-Avatar
WSBT

Ich habe einige Apps erstellt, die mehrere Themen unterstützen, aber ich musste die App immer neu starten, wenn der Benutzer das Thema wechselt, weil setTheme() muss vorher angerufen werden setContentView().

Ich war damit einverstanden, bis ich diese App entdeckte. Es kann nahtlos zwischen zwei Themen wechseln, und das auch mit Übergängen/Animationen!

Geben Sie hier die Bildbeschreibung ein

Bitte geben Sie mir einige Hinweise, wie dies implementiert wurde (und auch Animationen). Vielen Dank!

  • Ist das Video eine echte Bewerbung?

    – Schwarzer Gürtel

    11. Mai 2015 um 17:35 Uhr

  • @Blackbelt Ja, ich habe das Video/Gif aufgenommen. Die App heißt „Zhihu“.

    – WSBT

    11. Mai 2015 um 17:36 Uhr

  • Hey Freund, hast du eine Lösung für wechselnde Themen wie Zhihu gefunden?

    – Johannes Fehler

    15. August 2016 um 9:25 Uhr

  • @JohnError Noch nicht. Haben Sie eine Lösung? Wenn Sie nach einem suchen, stimmen Sie bitte die Frage für die Sichtbarkeit ab.

    – WSBT

    16. August 2016 um 20:07 Uhr

  • @ user1032613 hast du eine Lösung gefunden, viele Apps machen es jetzt?

    – Mateen Chaudhry

    26. März 2019 um 8:50 Uhr

Benutzer-Avatar
GKA

Die Antwort von @Alexander Hanssen hat dies im Grunde genommen … Ich weiß nicht, warum sie nicht akzeptiert wurde … Vielleicht wegen der finish()/startActivity(). Ich habe dafür gestimmt und versucht, einen Kommentar abzugeben, aber ich kann nicht …

Wie auch immer, ich würde genau das tun, was er in Bezug auf Stile beschrieben hat.

<style name="AppThemeLight" parent="Theme.AppCompat.Light">
    <!-- Customize your theme here. -->
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
    <!-- Customize your theme here. -->
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<!-- This will set the fade in animation on all your activities by default -->
<style name="WindowAnimationTransition">
    <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
    <item name="android:windowExitAnimation">@android:anim/fade_out</item>
</style>

Aber anstatt mit neuer Absicht zu beenden / zu beginnen:

Intent intent = new Intent(this, <yourclass>.class);
startActivity(intent);
finish();

Ich würde tun:

@Override
protected void onCreate(Bundle savedInstanceState) {

    // MUST do this before super call or setContentView(...)
    // pick which theme DAY or NIGHT from settings
    setTheme(someSettings.get(PREFFERED_THEME) ? R.style.AppThemeLight : R.style.AppThemeDark);

    super.onCreate(savedInstanceState);
}

// Somewhere in your activity where the button switches the theme
btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        // decide which theme to use DAY or NIGHT and save it
        someSettings.save(PREFFERED_THEME, isDay());

        Activity.this.recreate();
    }
});

Der Effekt ist wie im Video zu sehen…

  • Was ist der Unterschied zwischen dem Beenden der Erstellungsaktivität und der Neuerstellung der Aktivität. Beide erstellen die Aktivität neu. Nur diese Animation wird nicht sichtbar sein.

    – Android-Geek

    30. März 2019 um 10:04 Uhr

  • Es ist eine alte Frage, aber ich habe Probleme mit dieser Lösung. Genauer gesagt funktioniert bis auf die Animation alles wie erwartet. Ich habe auch versucht, eine benutzerdefinierte Animation zu verwenden, aber die Animation stoppt nach 20-30 ms, unabhängig von der Dauer, die ich in der XML-Datei festgelegt habe. Gleiches gilt für die von Ihnen vorgeschlagenen Aktienanimationen. Ich erstelle die Aktivität mit getActivity() in einem Fragment neu, das ich für die Einstellungen verwende.

    – Minar

    14. Oktober 2019 um 17:35 Uhr

  • @GKA Was ist mit den anderen Aktivitäten? Die Änderung spiegelt sich in derselben Aktivität wider, aber muss ich dasselbe Thema in jeder Aktivität anwenden?

    – Kischan Solanki

    27. März 2020 um 7:37 Uhr

  • Ich habe ein Problem mit dieser Lösung, ich verwende Fragmente in der Aktivität. Wenn ich die Aktivität neu starte, verliere ich Daten in den Fragmenten, z. B. die Position der Bildlaufliste.

    – Majid Sadeghi

    11. April 2020 um 12:16 Uhr


  • @MajidSadeghi Dies ist ein Standardproblem im Lebenszyklus von Android. Speichern und stellen Sie die benötigten Informationen in den Lebenszyklus-Hooks der Aktivität wieder her.

    – GKA

    12. April 2020 um 14:04 Uhr

Benutzer-Avatar
Alexander Hansen

Der Übergang/die Animation sorgt dafür, dass sich das Design nahtlos ändert, wenn Sie die Aktivität neu starten, und dies kann erreicht werden, indem Sie die Elemente „android:windowanimationStyle“ zu Ihren Designs hinzufügen und dann auf einen Stil verweisen, in dem Sie angeben, wie die Aktivität animiert werden soll, wenn sie eintritt und Ausgänge. Beachten Sie, dass die Animation dadurch auf alle Aktivitäten mit diesem Thema angewendet wird.

<style name="AppThemeLight" parent="Theme.AppCompat.Light">
    <!-- Customize your theme here. -->
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
    <!-- Customize your theme here. -->
    <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<!-- This will set the fade in animation on all your activities by default -->
<style name="WindowAnimationTransition">
    <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
    <item name="android:windowExitAnimation">@android:anim/fade_out</item>
</style>

Wenn Sie dann das Thema ändern möchten, können Sie dies tun, indem Sie auf eine Schaltfläche klicken:

AppSettings settings = AppSettings.getInstance(this);
settings.set(AppSettings.Key.USE_DARK_THEME,
!settings.getBoolean(AppSettings.Key.USE_DARK_THEME));
Intent intent = new Intent(this, <yourclass>.class);
startActivity(intent);
finish();

Dann in deiner onCreate Methode verwenden Sie die setTheme() So wenden Sie das Design an, das derzeit in AppSettings festgelegt ist:

AppSettings settings = AppSettings.getInstance(this);
setTheme(settings.getBoolean(AppSettings.Key.USE_DARK_THEME) ? R.style.AppThemeDark : R.style.AppThemeLight);
super.onCreate(savedInstanceState);
setContentView(<yourlayouthere>);

Schauen Sie sich diese Zusammenfassung als Referenz an: https://gist.github.com/alphamu/f2469c28e17b24114fe5

  • Während dies die Frage theoretisch beantworten kann, wäre es vorzuziehen, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen.

    – Enamul Hassan

    17. Februar 2016 um 10:08 Uhr

  • Vielen Dank für das Feedback, ich habe meine Antwort bearbeitet und die wesentlichen Teile eingefügt.

    – Alexander Hansen

    18. Februar 2016 um 9:14 Uhr

  • “Fertig stellen” beendet einfach die App..?

    – Daniel Springer

    22. Juni um 23:26 Uhr

für diejenigen, die versuchen, eine Lösung für Android Version 10 oder aktualisiert zu finden.

Um den Dunkel-/Hell-Modus einzustellen, verwenden Sie Folgendes:

AppCompatDelegate.setDefaultNightMode(state) //state can be AppCompatDelegate.MODE_NIGHT_YES or AppCompatDelegate.MODE_NIGHT_NO

Es ändert die Anzeige Ihrer App, jedoch mit einem Flimmern

Um das Flackern der Aktivitätserholung zu vermeiden (für einen reibungslosen Übergang), fügen Sie in Ihrer Aktivität die folgende Methode hinzu

@Override
    public void recreate() {
        finish();
        overridePendingTransition(R.anim.anime_fade_in,
                                  R.anim.anime_fade_out);
        startActivity(getIntent());
        overridePendingTransition(R.anim.anime_fade_in,
                                  R.anim.anime_fade_out);
    }

  • Während dies für Apps mit mehreren Aktivitäten gut aussehen mag, funktioniert es nicht immer richtig für Apps mit einer Aktivität / mehreren Fragmenten. In solchen Fällen führt das erneute Erstellen der Aktivität auf diese Weise den Benutzer nicht dorthin zurück, wo er war.

    – m_katsifarakis

    17. November 2021 um 22:26 Uhr

Nichts hindert Sie daran, anzurufen setTheme() und dann setContentView() wieder. Sie müssen Ihre App nur ein wenig umstrukturieren, sodass Sie bei einer Änderung des Designs alle Mitgliedsvariablen neu initialisieren müssen, auf die Sie möglicherweise verweisen View Objekte.

Benutzer-Avatar
Iman Dolatkia

setTheme() Vor super.onCreate (gespeicherterInstanzzustand) in GKA Antwort ist perfekter Ansatz und funktioniert gut, dank GKA.

aber es erstellt wieder neue Instanzen für alle Ressourcen, einschließlich Aktivitäten, Fragmente und Recycler-Ansichten. Ich denke, es kann eine schwere Arbeit sein und zum Verlust einiger gespeicherter Daten wie lokaler Variablen führen.

laut google dokument: https://developer.android.com/reference/android/app/Activity#recreate()

Veranlassen Sie, dass diese Aktivität mit einer neuen Instanz neu erstellt wird. Dies führt im Wesentlichen zu demselben Ablauf wie bei der Erstellung der Aktivität aufgrund einer Konfigurationsänderung – die aktuelle Instanz durchläuft ihren Lebenszyklus zu onDestroy() und danach wird eine neue Instanz erstellt.

Es gibt einen anderen Ansatz, bei dem Sie das Thema programmgesteuert mit Code (Java oder Kotlin) ändern können. Bei diesem Ansatz müssen Sie nicht alle Ressourcen neu erstellen, und Sie können auch benutzerdefinierte Animationen wie Ripple verwenden.

Überprüfen Sie meine GitHub-Bibliothek:
https://github.com/imandolatkia/Android-Animated-Theme-Manager

In dieser Bibliothek können Sie Ihre benutzerdefinierten Designs erstellen und sie dynamisch mit Ripple-Animation ändern, ohne Ressourcen neu erstellen zu müssen.

Geben Sie hier die Bildbeschreibung ein

Benutzer-Avatar
Ali Nawaz

Einfach effizient Einzeiler im Fragment:

requireActivity().recreate();

Für Aktivität:

recreate();

1249890cookie-checkWie wechselt man Themen (Nachtmodus), ohne die Aktivität neu zu starten?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy