BirjuVachhani / adaptive_theme

Easiest way to add support for light and dark theme in your flutter app.
https://pub.dev/packages/adaptive_theme
Apache License 2.0
464 stars 37 forks source link

Change Android Navigation Bar Color on System Dark Mode toggle #45

Closed iamhx closed 1 year ago

iamhx commented 1 year ago

When using AdaptiveTheme.of(context).modeChangeNotifier.addListener, I can change my android's navigation bar color like this:

AdaptiveTheme.of(context).modeChangeNotifier.addListener(() async {
      //This gets the system's platform brightness.
      final platformBrightness = MediaQuery.of(context).platformBrightness;

      final themeMode = AdaptiveTheme.of(context).mode;
      late Color color;
      late Brightness brightness;

      switch (themeMode) {
        case AdaptiveThemeMode.light:
          color = Colors.white;
          brightness = Brightness.dark;
          break;
        case AdaptiveThemeMode.dark:
          color = Colors.black;
          brightness = Brightness.light;
          break;
        case AdaptiveThemeMode.system:
          color = (platformBrightness == Brightness.dark)
              ? Colors.black
              : Colors.white;
          brightness = (platformBrightness == Brightness.dark)
              ? Brightness.light
              : Brightness.dark;
          break;
        default:
          break;
      }

      SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
          systemNavigationBarColor: color,
          systemNavigationBarIconBrightness: brightness));
});

However, the navigation bar color does not change when I toggle dark mode from my Notification Centre. I tried finding a way to listen for platform brightness here by using WidgetsBinding.instance.handlePlatformBrightnessChanged();, but this would disable the dynamic theming of the app provided in your package (As I realised that I am probably overriding your code).

Is there a way I can change the navigation bar color, when toggling dark mode from notification centre?

Example (Gif was too large to show here, sorry)

iamhx commented 1 year ago

It turns out that I used WidgetsBinding.instance.handlePlatformBrightnessChanged(); wrongly, as I had to do it inside the WidgetsBinding.instance.window.onPlatformBrightnessChanged instead...

var window = WidgetsBinding.instance.window;
    window.onPlatformBrightnessChanged = () async {
      // This callback is called every time the brightness changes.
      WidgetsBinding.instance.handlePlatformBrightnessChanged();
      final currentPlatformBrightness = window.platformBrightness;
      final currentThemeMode = await AdaptiveTheme.getThemeMode();

      switch (currentThemeMode) {
        case AdaptiveThemeMode.light:
          color = Colors.white;
          brightness = Brightness.dark;
          break;
        case AdaptiveThemeMode.dark:
          color = Colors.black;
          brightness = Brightness.light;
          break;
        case AdaptiveThemeMode.system:
          color = (currentPlatformBrightness == Brightness.dark)
              ? Colors.black
              : Colors.white;
          brightness = (currentPlatformBrightness == Brightness.dark)
              ? Brightness.light
              : Brightness.dark;
          break;
        default:
          break;
      }
      SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
          systemNavigationBarColor: color,
          systemNavigationBarIconBrightness: brightness));
    };

Now when the dark mode is toggled through the notification centre, the navigation bar color changes accordingly.

BirjuVachhani commented 1 year ago

@iamhx Glad you were able to make it work on your own. However, you don't need to register a listener. You can just set those properties if you can in your theme and let the package do its thing.

iamhx commented 1 year ago

@BirjuVachhani Thanks for the reply.

In my theme_light.dart:

final ThemeData lightTheme = ThemeData(
    appBarTheme: AppBarTheme(
        systemOverlayStyle: const SystemUiOverlayStyle(
        statusBarColor: Colors.transparent,
        statusBarIconBrightness: Brightness.dark,
        statusBarBrightness: Brightness.light,
        systemNavigationBarColor: Colors.green, //Trying to change color here, does not work.
      )
    );

Setting those properties in my theme doesn't seem to change anything and I am not sure why. That is why I had to use SystemChrome.setSystemUIOverlayStyle. Tried searching online on why that doesn't work, but haven't really found the answer to this issue. But as long as it works, I guess!

Thank you for this great package.

BirjuVachhani commented 1 year ago

I am not sure but I think you have to set brightness as well.

BrianMwas commented 1 year ago

I am not sure but I think you have to set brightness as well.

Brightness is deprecated

BrianMwas commented 1 year ago

It turns out that I used WidgetsBinding.instance.handlePlatformBrightnessChanged(); wrongly, as I had to do it inside the WidgetsBinding.instance.window.onPlatformBrightnessChanged instead...

var window = WidgetsBinding.instance.window;
    window.onPlatformBrightnessChanged = () async {
      // This callback is called every time the brightness changes.
      WidgetsBinding.instance.handlePlatformBrightnessChanged();
      final currentPlatformBrightness = window.platformBrightness;
      final currentThemeMode = await AdaptiveTheme.getThemeMode();

      switch (currentThemeMode) {
        case AdaptiveThemeMode.light:
          color = Colors.white;
          brightness = Brightness.dark;
          break;
        case AdaptiveThemeMode.dark:
          color = Colors.black;
          brightness = Brightness.light;
          break;
        case AdaptiveThemeMode.system:
          color = (currentPlatformBrightness == Brightness.dark)
              ? Colors.black
              : Colors.white;
          brightness = (currentPlatformBrightness == Brightness.dark)
              ? Brightness.light
              : Brightness.dark;
          break;
        default:
          break;
      }
      SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
          systemNavigationBarColor: color,
          systemNavigationBarIconBrightness: brightness));
    };

Now when the dark mode is toggled through the notification centre, the navigation bar color changes accordingly.

Hey instead of this you can use the following final currentBrightness = MediaQuery.platformBrightnessOf(context) Its way more performant in the long run