Switching themes dynamically in flutter apps by using provider

Nowadays, switching themes is one of the trending feature in every mobile application. By switching the themes, users can reduce their eye strain and increases mobile battery life. 

In this article, we are going to learn about how to switch themes dynamically using a Provider for state management and SharedPreferences to save the user decision.

We may achieve this in two ways: one, by adding a custom option, and the other, by automatically switching the theme based on system settings.

In Flutter, we can give the Theme across the app by providing the ThemeData to the MaterialApp constructor. The default theme will be shared across the app when no theme is provided. 

MaterialApp(
   theme: ThemeData( ... ), // declaring the theme to across the app
);

ThemeData(…) is like an ocean, we have plenty of properties to declare the theme to our app. We can see it on the official document here.

ThemeData.light() gives the Light blue theme, which is a default theme for every flutter application.

MaterialApp(
  theme: ThemeData.light(),  // default the theme 
);
Switching themes in the flutter apps

ThemeData.dark() gives the dark theme across the application 

MaterialApp(
   theme: ThemeData.dark(),  // default dark the theme 
);
Dark Theme - Switching themes in the flutter apps

Instead of using default theme colors, we can provide the own colors to primaryColor, accentColor, backgroundColor … to create a costume theme.

ThemeData(
          accentColor: Colors.red,
          brightness: Brightness.light,
          primaryColor: Colors.amber,
),
Switching themes in the flutter apps

Implementation of switching themes:

Now we got an idea about the themes in a flutter. Let’s Implement a custom option to change the theme dynamically in our app.

1.  Create a new Flutter project in your IDE. If you want to learn how to make a new Flutter project, check out this article


2. Once project creation has been done then add the latest versions of Provider and SharedPreference dependencies to our pubspec.yaml file

dependencies:
  flutter:
    sdk: flutter
  provider: <"latest version">
  shared_preferences: <"latest version">

Provider: Provider is one of the famous package for providing dependency injection and state management for flutter apps.
Shared preferences: Shared preference allows the storage of a minimal amount of primitive data as key/value pairs in a file on the device. It will keep the current theme status even user close the application.

3. Create a class for shared preference 
Let’s Create a dart file named theme_preference.dart, which includes two methods setTheme() for save the theme and getTheme() for retrieving the theme.

//Switching themes in the flutter apps - Flutterant
//theme_preference.dart
import 'package:shared_preferences/shared_preferences.dart';

class ThemePreferences {
  static const PREF_KEY = "pref_key";

  setTheme(bool value) async {
    SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
    sharedPreferences.setBool(PREF_KEY, value);
  }

  getTheme() async {
    SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
    return sharedPreferences.getBool(PREF_KEY) ?? false;
  }
}
//Switching themes in the flutter apps - Flutterant

4. Create a model for the provider
Let’s create a new dart file named theme_model.dart 

//theme_model.dart 
import 'package:flutter/material.dart';
import 'package:theme_switching_flutter_app/theme_preference.dart';

class ThemeModel extends ChangeNotifier {
  bool _isDark;
  ThemePreferences _preferences;
  bool get isDark => _isDark;

  ThemeModel() {
    _isDark = false;
    _preferences = ThemePreferences();
    getPreferences();
  }
//Switching themes in the flutter apps - Flutterant
  set isDark(bool value) {
    _isDark = value;
    _preferences.setTheme(value);
    notifyListeners();
  }

  getPreferences() async {
    _isDark = await _preferences.getTheme();
    notifyListeners();
  }
}
//Switching themes in the flutter apps - Flutterant
  • _isDark: boolean variable gives the status of the theme
  • _preferences: is an instance variable for ThemePreferences class
  • ThemeModel() constructor is to initialize the member variables and load the theme status from the shared preference by getPreference() method.
  • getPreference() method loads the theme status from shared preference and sets it to _isDark
  • notifyListerners() method to rebuild the UI based on the new value of _isDark 

 5. Add the provider to the Material app
Now wrap the MaterialApp with ChangeNotifierProvider. Then we can use ThemeModel to get the theme.

//main.dart
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => ThemeModel(),
      child: Consumer<ThemeModel>(
          builder: (context, ThemeModel themeNotifier, child) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: themeNotifier.isDark ? ThemeData.dark() : ThemeData.light(),
          debugShowCheckedModeBanner: false,
          home: MyHomePage(),
        );
      }),
    );
  }
}
//Switching themes in the flutter apps - Flutterant

And finally, we need to add the Consumer to listen and update the UI

//main.dart
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Consumer<ThemeModel>(
        builder: (context, ThemeModel themeNotifier, child) {
      return Scaffold(
        appBar: AppBar(
          title: Text(themeNotifier.isDark ? "Dark Mode" : "Light Mode"),
          actions: [
            IconButton(
                icon: Icon(themeNotifier.isDark
                    ? Icons.nightlight_round
                    : Icons.wb_sunny),
                onPressed: () {
                  themeNotifier.isDark
                      ? themeNotifier.isDark = false
                      : themeNotifier.isDark = true;
                })
          ],
        ),
        body: ListView.builder(itemBuilder: (BuildContext context, int index) {
          return Container(
            child: Card(
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10)),
              child: Padding(
                padding: const EdgeInsets.all(12.0),
                child: Text(
                  "Lorem Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industry's standard dummy text ever since the 1500s.",
                  style: TextStyle(fontSize: 14),
                ),
              ),
            ),
          );
        }),
      );
    });
  }
}
//Switching themes in the flutter apps - Flutterant


Implementation part is done, Let’s see the output

Switching themes in the flutter apps

We can change the theme based on the system preferences by providing the light ThemeData to the theme parameter and dark ThemeData to the darkTheme parameter.

  theme: ThemeData.light(), // Provide light theme.
  darkTheme: ThemeData.dark(), // Provide dark theme.
  themeMode: ThemeMode.system, //to follow the system theme


Thanks for reading !!! 🙂

1 thought on “Switching themes dynamically in flutter apps by using provider”

Leave a Comment