Dynamic Theme in Flutter – Dark and Light theme

Adding Light and Dark theme for your app kind of become mandatory thing in todays app world. Because most people prefer dark theme over light theme because it pretty comfortable for our eyes.

In this tutorial we are going to implement a simple flutter app to switch between light and dart theme without much complicated code.

First thing first, Let’s create a simple UI with a switch with in it. This switch will change the variable called _light to true or false based on the user interaction.

    
            Switch(
                  value: _light, 
                  onChanged: (toggle){
                    
                  }),
    

In because we are changing the state of the App we need use stateful widget in here.

The simplest way of changing the light to dark is by changing the theme of the MaterialApp widget to light to dark. For that we need two themes like dark and light.

    
            ThemeData _darkTheme = ThemeData(
              accentColor: Colors.red,
              brightness: Brightness.dark,
              primaryColor: Colors.amber,
            
            );
            
            ThemeData _lightTheme = ThemeData(
              accentColor: Colors.pink,
              brightness: Brightness.light,
              primaryColor: Colors.blue
            );
    

When defining theme, you can select the accentColor and primaryColour based on your need . The important part is we have to mentioned the brightness whether is dark or light for each ThemeData class.

The next thing is based on the _light variable value, we can set the MaterialApp theme property to either light ThemeData object or dark one.

    
             MaterialApp(
              theme: _light ? _lightTheme : _darkTheme,
              title: 'Material App')
    

Don’t forget to apply setState to Switch widget onChange callback.

    
                Switch(
                  value: _light, 
                  onChanged: (toggle){
                    setState(() {
                      _light = toggle;
                    });
                  })
    

Now you can see the app theme get changed nicely when you toggle the switch.

flutter light dark theme

Hard cording Theme values

In because we are changing theme it bettor to not hardcoding some element like text and button colours. Because some of the hard corded colours may not be properly shows in dark or light theme.

Changing Button colours

You can set the default button color by setting buttonColor property. Also if you want more control of the button to change disable colour, height, padding etc. you can create a button theme.

    
        ThemeData _darkTheme = ThemeData(
          accentColor: Colors.red,
          brightness: Brightness.dark,
          primaryColor: Colors.amber,
        
          buttonTheme: ButtonThemeData(
            buttonColor: Colors.amber,
            disabledColor: Colors.black
          )
        );

Adapt Theme based on the System Theme

If you have enabled the dark appearance of your phone you can set the default dark theme by specifying darkTheme property in MaterialApp widget. You can use the same dark Theme data object which we created previously. Now when you switch you phone to dark mode app will turn into dark mode automatically without changing. In this case switching from toggle not work in because we are forcefully changing the colour.

    
    MaterialApp(
          theme: _light ? _lightTheme : _darkTheme,
          title: 'Material App',
          darkTheme: _darkTheme)
    

Keep the selected theme persistently

If you want to keep the current theme selection even the user close the application you need to save the currently selected theme in a persistent way.

In the Flutter we can use shared preferences library to save current selected theme and check and set the theme when application get loaded.

Add the dependency and install

    
   dependencies:
    shared_preferences: ^0.5.7+3
    
        flutter pub get
    

Import plugin to dart code

       import 'package:shared_preferences/shared_preferences.dart';
    

Now you can use this plugin functionality. First lets create a two methods to save and retrieve the theme values

      Future <SharedPreferences> _prefs = SharedPreferences.getInstance();

        _saveTheme() async{
            SharedPreferences pref = await _prefs;
            pref.setBool('theme', _light);
          }
        
          _getTheme() async{
            _lightF = _prefs.then((SharedPreferences prefs) {
                return prefs.getBool('theme') != null ? prefs.getBool('theme') : true;
            });
            _light = await _lightF;
          }
    

When the initState method get called you can call the _getTheme method to get the current saved theme.

      @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _getTheme();
  }
    

Getting the values from the shared preferences and setting the value to shared preferences happen in an asynchronous way. Therefore we need to use the FutureBuilder widget to assign the theme after the retrieving part gets completed.

Therefore you can wrap the MaterialApp widget inside FutureBuilder widget and set the future property as a _lightF variable value.

Finally, you need to call the _saveTheme method when the user changes the switch from dark to light or vice versa.

     
        Switch(value: _light, onChanged: (state){
                  setState(() {
                    _light = state;
                  });
                  _saveTheme();
                }),
    

If the application already running, stop the running process and run the application again to see the changes.

You Will Like Also