I'm setting up my app to be able to switch the app's theme color from white to dark. I installed the provider package and when switching between pages, the settings are saved. But if the page is refreshed or closed and reopened, the settings are lost. How can I fix this? I leave the switching code below, but if you need any way to answer my question, let me know
main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (context) => ThemeProvider(),
builder: (context, _) {
final themeProvider = Provider.of<ThemeProvider>(context);
return MaterialApp(
debugShowCheckedModeBanner: false,
themeMode: themeProvider.themeMode,
theme: MyThemes.lightTheme,
darkTheme: MyThemes.darkTheme,
initialRoute: '/',
routes: {
'/': (context) => LoginPage(),
'/profile-user': (context) => (ProfileUser()),
});
});
}
change_button.dart
import 'package:flutter/material.dart';
import 'package:itda_fe_mobile/theme_provider.dart';
import 'package:provider/provider.dart';
class ChangeThemeButtonWidget extends StatelessWidget {
const ChangeThemeButtonWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final themeProvider = Provider.of<ThemeProvider>(context);
return Switch.adaptive(
value: themeProvider.isDarkMode,
onChanged: (value) {
final provider = Provider.of<ThemeProvider>(context, listen: false);
provider.toggleTheme(value);
},
);
}
}
theme_provider.dart
class ThemeProvider extends ChangeNotifier {
ThemeMode themeMode = ThemeMode.system;
bool get isDarkMode {
if (themeMode == ThemeMode.system) {
final brightness = SchedulerBinding.instance?.window.platformBrightness;
return brightness == Brightness.dark;
} else {
return themeMode == ThemeMode.dark;
}
}
void toggleTheme(bool isOn) {
themeMode = isOn ? ThemeMode.dark : ThemeMode.light;
notifyListeners();
}
}
class MyThemes {
static final darkTheme = ThemeData(
scaffoldBackgroundColor: Colors.grey.shade900,
primaryColor: Colors.black,
colorScheme: ColorScheme.dark(),
iconTheme: IconThemeData(color: Colors.purple.shade200, opacity: 0.8),
);
static final lightTheme = ThemeData(
scaffoldBackgroundColor: Colors.white,
primaryColor: Colors.white,
colorScheme: ColorScheme.light(),
iconTheme: IconThemeData(color: Colors.red, opacity: 0.8),
);
}
CodePudding user response:
Original Answer
Settings like these can be stored in the SharedPreferences
of the app. Take a look at the package:
https://pub.dev/packages/shared_preferences
To install it, you can copy its installation line to your pubspec.yaml
file, or run `pub add'.
flutter pub add shared_preferences
To use it, you can add some code where you currently switch your theme.
// add this code to get an instance and set the new value of isDarkMode
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool('isDarkMode', value);
Then when you start your app (when/before you initialize your provider), you can read the value from the shared preferences and use that.
SharedPreferences prefs = await SharedPreferences.getInstance();
bool initialValue = prefs.getBool('isDarkMode');
Full example with your code
// Main is now an async function, so we can call SharedPreferences.getInstance()
void main() async {
// Before starting the app, we want to check in the settings whether we were using dark mode or not in the last session
// Before calling any plugin, we need to make sure the Widget binding is initialized (leaving this out will crash the app!)
WidgetsFlutterBinding.ensureInitialized();
// We get the initial isDarkMode from the settings or otherwise just the system theme mode
SharedPreferences prefs = await SharedPreferences.getInstance();
bool initialIsDarkMode = prefs.getBool('isDarkMode') ?? ThemeMode.system == ThemeMode.dark;
// We pass down this boolean value to the app
runApp(MyApp(initialIsDarkMode));
}
class MyApp extends StatelessWidget {
// The boolean value is stored in the Widget
final bool initialIsDarkMode;
const MyApp(this.initialIsDarkMode, {key}) : super(key: key);
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
// We now pass down this boolean to the ThemeProvider, so it knows what to start with
create: (context) => ThemeProvider(initialIsDarkMode),
builder: (context, _) {
...
},
);
Then in ThemeProvider
:
class ThemeProvider extends ChangeNotifier {
ThemeMode themeMode;
// Constructor which takes in the bool, and initializes the themeMode accordingly
ThemeProvider(bool initialIsDarkMode)
: themeMode = initialIsDarkMode ? ThemeMode.dark : ThemeMode.light;
...
void toggleTheme(bool isOn) async {
themeMode = isOn ? ThemeMode.dark : ThemeMode.light;
// also store it in the preferences (in case the app is closed after this)
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool('isDarkMode', isOn);
notifyListeners();
}
...
}