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);
}
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.
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();
}
...