Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

flutter theme

Dynamic Theme in Flutter – Dark and Light theme

Applying dark and the light theme for Flutter app

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

In this tutorial, we are going to implement a simple flutter app to switch between light and dark themes without much-complicated code.

First thing first, Let’s create a simple UI with a switch within 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 to use the stateful widget 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 a theme, you can select the accentColor and primaryColour based on your need . The important part is we have to mention 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.

Hard cording Theme values

In because we are changing the theme it is better to not hardcoding some elements like text and button colours. Because some of the hard corded colours may not be properly shown 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 your phone to dark mode app will turn into dark mode automatically without changing. In this case, switching from toggle does not work 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 the shared preferences library to save the current selected theme and check and set the theme when the application gets 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, let’s create 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 gets 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.