Reputation: 117
I've implemented the theme for the app theme_managers.dart and I've done SharedPreferences on the theme.dart. But the problem is the SharedPreferences on the switch it's working when. I reopen the app it still getting data from last action but the theme(dark mode) get reset all the time when reopen the app.
I don’t understand if I need to put the SharedPreferences on the theme_manager.dart or not. If you know Please point out the problem or some code. Thanks
Please look though my code and you’ll understand the problem.
In theme.dart(some) :
bool colorMode = false;
@override
void initState() {
super.initState();
getSwitchValues();
}
getSwitchValues() async {
colorMode = await loadbool();
setState(() {});
}
Future<bool> savebool(bool value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
themeManager.toggleTheme(value);
prefs.setBool("colorMode", value);
return prefs.setBool("colorMode", value);
}
Future<bool> loadbool() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool? colorMode = prefs.getBool("colorMode");
return colorMode!;
}
//Switch
Switch(
activeColor: Colors.grey,
value: colorMode,
onChanged: (bool value) {
setState(() {
themeManager.toggleTheme(value);
colorMode = value;
savebool(value);
});
}),
In theme_manager.dart :
class ThemeManager extends ChangeNotifier {
ThemeMode _themeMode = ThemeMode.light;
get themeMode => _themeMode;
toggleTheme(bool isDark){
_themeMode = isDark? ThemeMode.dark :ThemeMode.light;
notifyListeners();
}
}
In main.dart(some) :
ThemeManager themeManager = ThemeManager();
@override
void initState() {
themeManager.addListener(themeListener);
super.initState();
}
@override
void dispose() {
themeManager.removeListener(themeListener);
super.dispose();
}
themeListener() {
if (mounted) {
setState(() {});
}
}
MultiProvider(
Provider(create: (_) => User),
ChangeNotifierProvider(create: (context) => themeManager)
],
child: MaterialApp(
title: 'My app',
themeMode: themeManager.themeMode,
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
home: const LoginScreen(),
debugShowCheckedModeBanner: false,
),
);
I forgot to mention my theme_constant.dart :
const colorPrimary = Colors.black;
const colorAccent = Colors.black;
ThemeData lightTheme = ThemeData(
brightness: Brightness.light,
primaryColor: colorPrimary,
floatingActionButtonTheme:
const FloatingActionButtonThemeData(backgroundColor: colorAccent),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
padding: MaterialStateProperty.all<EdgeInsetsGeometry>(
const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0)),
shape: MaterialStateProperty.all<OutlinedBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0))),
backgroundColor: MaterialStateProperty.all<Color>(colorAccent))),
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
borderSide: BorderSide.none),
filled: true,
fillColor: Colors.grey.withOpacity(0.1)));
ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
switchTheme: SwitchThemeData(
trackColor: MaterialStateProperty.all<Color>(Colors.black),
thumbColor: MaterialStateProperty.all<Color>(Colors.black),
),
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(0.0),
borderSide: BorderSide.none),
filled: true,
fillColor: Colors.black.withOpacity(0.0)),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
padding: MaterialStateProperty.all<EdgeInsetsGeometry>(
const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0)),
shape: MaterialStateProperty.all<OutlinedBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0))),
backgroundColor: MaterialStateProperty.all<Color>(Colors.white),
foregroundColor: MaterialStateProperty.all<Color>(Colors.black),
overlayColor: MaterialStateProperty.all<Color>(Colors.black))),
);
I am not sure If the problem is from here too?
Upvotes: 0
Views: 203
Reputation: 63594
Material directly using themeManager.themeMode
which returns the ThemeMode.light
themeMode: themeManager.themeMode,
You might create a method, and make sure to get data from this future before providing on materialApp
class ThemeManager extends ChangeNotifier {
ThemeMode _themeMode = ThemeMode.light;
ThemeMode get themeMode => _themeMode;
Future<void> initTheme() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool? colorMode = prefs.getBool("colorMode");
// switch if needed
_themeMode = colorMode == true ? ThemeMode.dark : ThemeMode.light;
notifyListeners();
}
Upvotes: 0
Reputation: 82
Try to load the ThemeMode before calling runApp() in your main method, e. g. by adding this to your main method:
void main() async {
ThemeManager themeManager = ThemeManager();
await themeManager.loadTheme(); // load the theme before running the app
runApp(
MultiProvider(
providers: [
Provider(create: (_) => User),
ChangeNotifierProvider(create: (context) => themeManager),
],
child: MaterialApp(
title: 'My app',
themeMode: themeManager.themeMode, // now the theme mode is the one loaded from shared prefs
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
home: const LoginScreen(),
debugShowCheckedModeBanner: false,
),
),
);
}
And for this to work, add the loadTheme()
method to your ThemeManager class:
class ThemeManager extends ChangeNotifier {
ThemeMode _themeMode = ThemeMode.light;
get themeMode => _themeMode;
toggleTheme(bool isDark){
_themeMode = isDark? ThemeMode.dark :ThemeMode.light;
notifyListeners();
}
Future<void> loadTheme() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool isDark = prefs.getBool("colorMode") ?? false;
_themeMode = isDark ? ThemeMode.dark : ThemeMode.light;
}
}
Upvotes: 1