Search code examples
androidandroid-theme

How to switch themes (night mode) without restarting the activity?


I have made a few apps that support multiple themes, but I always had to restart the app when user switches theme, because setTheme() needs to be called before setContentView().

I was okay with it, until I discovered this app. It can seamlessly switch between two themes, and with transitions/animations too!

enter image description here

Please give me some hints on how this was implemented (and animations too). Thanks!


Solution

  • @Alexander Hanssen's answer basically has answered this... Don't know why it was not accepted... Maybe because of the finish()/startActivity(). I voted for it and I tried to comment but cannot...

    Anyway, I would do exactly what he described in terms of 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>
    

    But instead of finish/start with new intent:

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

    I would do:

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

    The effect is as shown in the video...