Search code examples
flutterthemes

How to listen for changes to platformBrightness in Flutter?


I'm setting up a system where when the user changes the system theme to dark mode, it changes the theme and with Flutter, it works all well and good! However, when the user changes the system theme, the system navigation and status bar don't change their colors. I have code running on the home page inside the build method but that doesn't seem to do it. Here's the code inside the home page build method:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Brightness sysBrightness = MediaQuery.of(context).platformBrightness;
    if (sysBrightness == Brightness.dark)
      Themes.setDarkSystemColors();
    else
      Themes.setLightSystemColors();

    return Scaffold(
      appBar: CustomAppBar(title: "Home"),
      drawer: CustomDrawer(),
      body: SizedBox(),
    );
  }
}

Here's the code in the main app with theme: and darkTheme::

    return MaterialApp(
      initialRoute: '/',
      routes: routes,
      navigatorObservers: [_routeObserver],
      theme: Themes.lightTheme,
      darkTheme: Themes.darkTheme,
      debugShowCheckedModeBanner: false,
      title: 'School Life',
    );

Solution

  • You can do it in many ways:

    • Using didChangeDependencies

      // This callback will be invoked every time the platform brightness changes.
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
      
        // Get the brightness. 
        var brightness = MediaQuery.of(context).platformBrightness;
      }
      
    • Using WidgetsBindingObserver

      class _MyPageState extends State<MyPage> with WidgetsBindingObserver {
        @override
        void initState() {
          super.initState();
          WidgetsBinding.instance.addObserver(this);
        }
      
        // This callback is invoked every time the platform brightness changes. 
        @override
        void didChangePlatformBrightness() {
          super.didChangePlatformBrightness();
      
          // Get the brightness.
          var brightness = View.of(context).platformDispatcher.platformBrightness;
        }
      
        @override
        void dispose() {
          WidgetsBinding.instance.removeObserver(this);
          super.dispose();
        }
      
        @override
        Widget build(BuildContext context) => Container();
      }
      
    • Setting listener in initState

      @override
      void initState() {
        super.initState();
      
        var dispatcher = SchedulerBinding.instance.platformDispatcher;
      
        // This callback is called every time the brightness changes. 
        dispatcher.onPlatformBrightnessChanged = () {
          var brightness = dispatcher.platformBrightness;
        };
      }