flutterflutter-theme

Flutter Theme Dark/Lights Theme toggle doesn't work


there is a dark/light theme toggle function in this snap of code. There is no error when I compile, debuging this code. But It doesn't work.

For example, I never define scaffoldbackgroundColor(0xfffafafa) and What I define color in dark, light theme is Color(0xFFE7626C) and Color(0xFF232B55). But ios simulator only show me backgroundcolor(0xfffafafa).

When I click toggle button, the screen never changes. What's wrong with my code...

import 'package:flutter/material.dart';
import 'package:pomodoro_app/widget/sidebar_widget.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  static final ValueNotifier<ThemeMode> themeNotifier =
      ValueNotifier(ThemeMode.dark);

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<ThemeMode>(
      valueListenable: themeNotifier,
      builder: (_, ThemeMode currentMode, __) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            brightness: Brightness.light,
            scaffoldBackgroundColor: const Color(0xFFE7626C),
            textTheme: const TextTheme(
              displayLarge: TextStyle(
                color: Color(0xFF232B55),
              ),
              displaySmall: TextStyle(
                color: Color(0xFF232B55),
              ),
            ),
            cardColor: const Color(0xFFF4EDDB),
          ),
          darkTheme: ThemeData(
            brightness: Brightness.dark,
            scaffoldBackgroundColor: const Color(
              0xFF232B55,
            ),
            cardColor: const Color(0xFFF4EDDB),
            textTheme: const TextTheme(
              displayLarge: TextStyle(
                color: Color(0xFFE7626C),
              ),
              displaySmall: TextStyle(
                color: Colors.white,
              ),
            ),
          ),
          themeMode: currentMode,
          home: Scaffold(
            appBar: AppBar(
              backgroundColor: Theme.of(context).scaffoldBackgroundColor,
              elevation: 0,
              leading: Builder(
                builder: (context) => IconButton(
                  onPressed: () => Scaffold.of(context).openDrawer(),
                  icon: const Icon(
                    Icons.menu_rounded,
                    color: Color(0xFFF4EDDB),
                  ),
                ),
              ),
              actions: [
                IconButton(
                  icon: Icon(themeNotifier.value == ThemeMode.light
                      ? Icons.dark_mode
                      : Icons.light_mode),
                  onPressed: () {
                    setState(
                      () {
                        themeNotifier.value =
                            themeNotifier.value == ThemeMode.light
                                ? ThemeMode.dark
                                : ThemeMode.light;
                      },
                    );
                  },
                ),
              ],
            ),
            drawer: const SideBar(),
            backgroundColor: Theme.of(context).scaffoldBackgroundColor,
            body: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: const [
                Text(
                  "Hello",
                )
              ],
            ),
          ),
        );
      },
    );
  }
}


Solution

  • That's because the context you are using with

    Theme.of(context);
    

    comes from the build method of _HomeScreenState. So this context is above the MaterialApp which has the Theme.

    You have to use a context that is bellow the MaterialApp.

    One way to do it is to add a Builder in between your MaterialApp and Scaffold:

    return MaterialApp(
      title: 'Flutter Demo',
      theme: // ...
      darkTheme: // ...
      themeMode: currentMode,
      home: Builder( // <- Insert a builder here.
        builder: (context) {  // <- Now you'll be using this `context` which is below the `MaterialApp` (and your themes) in the widget tree, so you'll be able to use them.
          return Scaffold(
            // ...
          );
      },
    );