Search code examples
flutterflutter-provider

Flutter provider color isn't change


My requirement is based on the system theme mode color will change dynamically. When the System theme is dark the primary color will be light green. When the System theme is light the primary color will be dark blue. The model I used for the theme

class AppThemeData {
  Color primaryColor;
  Color secondaryColor;
  AppThemeData({
     required this.primaryColor,
     required this.secondaryColor,
  });
}

The theme variable I used

AppThemeData darkModeTheme = AppThemeData(
    primaryColor: const Color.fromARGB(255, 9, 230, 127),
    secondaryColor: const Color.fromARGB(255, 255, 0, 179),
);
AppThemeData lightModeTheme = AppThemeData(
    primaryColor: const Color(0xFF796BFF),
    secondaryColor: const Color(0xFFFF3D00),
);

Provider class function code

class AppTheme with ChangeNotifier {
    static var brightness = SchedulerBinding.instance!.window.platformBrightness;
    static bool _isDarkMode = brightness == Brightness.dark;
    static AppThemeData _theme =
        _isDarkMode == true ? darkModeTheme : lightModeTheme;

    bool get isDarkMode => _isDarkMode;
    AppThemeData get theme => _theme;

    changeAppThemeMode(bool appIsDarkMode) {
    _isDarkMode = appIsDarkMode;
    _isDarkMode == true ? _theme = darkModeTheme : _theme = lightModeTheme;
    notifyListeners();
    return "theme";
    }
}

Simple Widget I use the Container

Container(
    height: 100,
    width: 100,
    color: Provider.of<AppTheme>(context, listen: false).theme.primaryColor
)

When Brightness changes automatically function will execute

@override
void didChangePlatformBrightness() {
  var brightness = SchedulerBinding.instance!.window.platformBrightness;
  bool isDarkMode = brightness == Brightness.dark;

  setState(() {
    Provider.of<AppTheme>(context, listen: false)
        .changeAppThemeMode(isDarkMode);
  });

  widget.onBrightnessChanged?.call();
  super.didChangePlatformBrightness();
}

App ThemeData I called like this

MaterialApp(
  debugShowCheckedModeBanner: false,
  title: 'Find Pic',
  theme: ThemeData(
    brightness: Brightness.light,
    primarySwatch: buildMaterialColor(Provider.of<AppTheme>(context, listen: true).theme.primaryColor)),
  darkTheme: ThemeData(
    brightness: Brightness.dark,
    primarySwatch: buildMaterialColor(Provider.of<AppTheme>(context, listen:true).theme.primaryColor)),
  themeMode: ThemeMode.system,
  home: const MyHomePage(),
);

buildMaterialColor function convert Colors to MaterialColor my

MaterialColor buildMaterialColor(Color color) {
  List strengths = <double>[.05];
  Map<int, Color> swatch = <int, Color>{};
  final int r = color.red, g = color.green, b = color.blue;

  for (int i = 1; i < 10; i++) {
    strengths.add(0.1 * i);
  }
  for (var strength in strengths) {
    final double ds = 0.5 - strength;
    swatch[(strength * 1000).round()] = Color.fromRGBO(
      r + ((ds < 0 ? r : (255 - r)) * ds).round(),
      g + ((ds < 0 ? g : (255 - g)) * ds).round(),
      b + ((ds < 0 ? b : (255 - b)) * ds).round(),
      1,
    );
  }
  return MaterialColor(color.value, swatch);
}

Solution

  • Most probably you've forgotten to initialize the widget's instance as an observer of WidgetsBindingObserver. It should be like the following by overriding initState and dispose methods.

    Live demo on DartPad

    class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
    
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
      }
    
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    
      @override
      void didChangePlatformBrightness() {
        var brightness = SchedulerBinding.instance.window.platformBrightness;
        bool isDarkMode = brightness == Brightness.dark;
    
        setState(() {
          Provider.of<AppTheme>(context, listen: false)
              .changeAppThemeMode(isDarkMode);
        });
    
        widget.onBrightnessChanged?.call();
        super.didChangePlatformBrightness();
      }
    
      ...