Flutter: 2 Ways to Make a Dark/Light Mode Toggle

Last updated on May 28, 2021 A Goodman Loading... Post a comment

This article walks you through a couple of different ways to switch between dark mode and light mode in a Flutter application.

Using Self-Written Code

This approach uses ValueListenableBuilder and ValueNotifier, the two built-in classes of Flutter.

App Preview

This sample app contains two screens: HomeScreen and OtherScreen. When you change the theme by tapping the button in the app bar, the color scheme of the entire app will change. The purpose of adding OtherScreen is to illustrate that.

If you look closely, you can also see that the icon of the button on the appBar also changes depending on the theme being applied.

The Complete Code

// main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // Using "static" so that we can easily access it later
  static final ValueNotifier<ThemeMode> themeNotifier =
      ValueNotifier(ThemeMode.light);

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<ThemeMode>(
        valueListenable: themeNotifier,
        builder: (_, ThemeMode currentMode, __) {
          return MaterialApp(
            // Remove the debug banner
            debugShowCheckedModeBanner: false,
            title: 'Kindacode.com',
            theme: ThemeData(primarySwatch: Colors.amber),
            darkTheme: ThemeData.dark(),
            themeMode: currentMode,
            home: HomeScreen(),
          );
        });
  }
}

// Home Screen
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Kindacode.com'),
        actions: [
          IconButton(
              icon: Icon(MyApp.themeNotifier.value == ThemeMode.light
                  ? Icons.dark_mode
                  : Icons.light_mode),
              onPressed: () {
                MyApp.themeNotifier.value =
                    MyApp.themeNotifier.value == ThemeMode.light
                        ? ThemeMode.dark
                        : ThemeMode.light;
              })
        ],
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to Other Screen'),
          onPressed: () {
            Navigator.push(context,
                MaterialPageRoute(builder: (context) => OtherScreen()));
          },
        ),
      ),
    );
  }
}

// Other Screen
class OtherScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Other Screen'),
      ),
      body: Center(
        child: Text(
          'Hello',
          style: TextStyle(fontSize: 50),
        ),
      ),
    );
  }
}

Using A Third-Party Plugin

There’re several good plugins that can help you easily implement dark/light mode in your app such as theme_provider, day_night_switcher, get (aka GetX).

In the following example, we’ll use GetX. You can install it by running:

flutter pub add get

App Preview

This sample app similar to the previous one.

The Code

To switch theme using GetX, you need to wrap your widget tree with GetMaterialApp instead of MaterialApp, like this:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      // Remove the debug banner
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      darkTheme: ThemeData.dark(),
      themeMode: ThemeMode.system,
      // Theme mode depends on device settings at the beginning
      home: HomeScreen(),
    );
  }
}

GetMaterialApp is not a modified MaterialApp, it is just a pre-configured widget, which has the default MaterialApp as a child.

Now you can use the changeTheme() method to turn the dark mode on or off:

Get.changeTheme(
                    Get.isDarkMode ? ThemeData.light() : ThemeData.dark());

The complete code:

// main.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      // Remove the debug banner
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      darkTheme: ThemeData.dark(),
      themeMode: ThemeMode.system,
      // Theme mode depends on device settings at the beginning
      home: HomeScreen(),
    );
  }
}

// Home Screen
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Kindacode.com'),
        actions: [
          IconButton(
              icon: Icon(Icons.lightbulb),
              onPressed: () {
                Get.isDarkMode
                    ? Get.changeTheme(ThemeData.light())
                    : Get.changeTheme(ThemeData.dark());
              })
        ],
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to Other Screen'),
          onPressed: () {
            Navigator.push(context,
                MaterialPageRoute(builder: (context) => OtherScreen()));
          },
        ),
      ),
    );
  }
}

// Other Screen
class OtherScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Other Screen'),
      ),
      body: Center(
        child: Card(
          child: Container(
              width: 300,
              height: 300,
              alignment: Alignment.center,
              child: Text('Other Screen')),
        ),
      ),
    );
  }
}

Note: In production apps, you should store the user settings somewhere like shared_preferences, SQLite, Hive database, Firebase, etc. For more information, see 4 Ways to Store Data Offline in Flutter and Flutter and Firestore Database: CRUD example.

Conclusion

You’ve learned a few techniques to implement dark/light mode toggle in an app. Choose the most suitable and convenient method for your project to provide your users the best experience. If you’d like to explore more new and exciting things about Flutter, take a look at the following articles:

You can also take a tour around our Flutter topic page, or Dart topic page for the latest tutorials and examples.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Related Articles