Comment changer de thème (Mode nuit) sans redémarrer l'activité?

j'ai fait un peu d'applications qui prennent en charge plusieurs thèmes, mais j'ai toujours eu à redémarrer l'application lorsque l'utilisateur change de thème, car setTheme() doit être appelée avant setContentView().

j'étais d'accord avec ça, jusqu'à ce que je découvre cette application. Il peut basculer sans problème entre deux thèmes, et aussi avec des transitions/animations!

enter image description here

veuillez me donner quelques conseils sur la façon dont cela a été mis en œuvre (et des animations aussi). Merci!

21
demandé sur MiguelHincapieC 2015-05-11 20:33:01

3 réponses

la réponse de@Alexander Hanssen a essentiellement répondu à cela... Je ne sais pas pourquoi ça n'a pas été accepté... Peut-être à cause du finish()/startActivity(). J'ai voté pour et j'ai essayé de commenter, mais je ne peux pas...

quoi qu'il en soit, je ferais exactement ce qu'il a décrit en termes de styles.

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

mais au lieu de finir/commencer avec une nouvelle intention:

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

je voudrais faire:

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

L'effet est tel que montré dans la vidéo...

22
répondu GKA 2016-12-23 13:46:03

la transition / animation rend le changement de thème seamless lorsque vous redémarrez l'activité, et cela peut être fait en ajoutant les éléments "android:windowanimationStyle" à vos thèmes, puis en référençant un style où vous spécifiez comment l'activité devrait s'animer quand elle entre et sort. Notez que cela fait que l'animation s'applique à toutes les activités avec ce thème.

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

Ensuite, lorsque vous souhaitez changer de thème, vous pouvez le faire en cliquant sur une bouton:

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

Puis dans votre onCreate méthode, utilisez le setTheme() pour appliquer le thème qui est actuellement défini dans AppSettings comme ceci:

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

consulter ce résumé de référence: https://gist.github.com/alphamu/f2469c28e17b24114fe5

7
répondu Alexander Hanssen 2016-02-18 09:13:44

rien ne vous empêche d'appeler setTheme() et setContentView() encore une fois. Vous aurez juste besoin de restructurer un peu votre application de sorte que, si vous changez le thème, vous devez réinitialiser toutes les variables membres que vous pourriez avoir qui contiennent des références à View objets.

1
répondu David Wasser 2015-05-11 17:47:26