Reputation: 65
I have added dark and light mode in my app but I am unable to save the mode selected. I am new so that's why I'm unable to understand what to do. Here's my code of dark and light mode button though which upon tapping it changes the mode.
ListTile(
onTap: () {
MyApp.themeNotifier.value =
MyApp.themeNotifier.value == ThemeMode.light
? ThemeMode.dark
: ThemeMode.light;
},
leading: Icon(MyApp.themeNotifier.value == ThemeMode.light
? Icons.dark_mode
: Icons.light_mode),
title: MyApp.themeNotifier.value == ThemeMode.light
? Text(
"Dark Mode",
style: TextStyle(
fontFamily: "Lato",
),
)
: Text(
"Light Mode",
style: TextStyle(
fontFamily: "Lato",
),
),
),
I want the mode to get selected. I know shared preferences and some other local databases can be used but how can anyone please tell by code snippet etc which I can implement please, Thanks
Upvotes: 2
Views: 1468
Reputation: 4824
Here's how it's possible to do this using Riverpod state management and Shared preferences database.
Required imports:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
Creating a provider SharedPreferences:
// provider stores the instance SharedPreferences
final sharedPreferencesProvider = Provider<SharedPreferences>((_) {
return throw UnimplementedError();
});
Creating a ChangeNotifierProvider returning AppTheme.
// provider to work with AppTheme
final appThemeProvider = ChangeNotifierProvider((ref) {
return AppTheme(ref.watch(sharedPreferencesProvider));
});
class AppTheme extends ChangeNotifier {
AppTheme(this._prefs);
final SharedPreferences _prefs;
/// Get the current value from SharedPreferences.
bool getTheme() => _prefs.getBool('isDarkMode') ?? false;
/// Store the current value in SharedPreferences.
void setTheme(bool isDarkMode) {
_prefs.setBool('isDarkMode', isDarkMode);
notifyListeners();
}
}
Note that main method is asynchronous:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// initialization SharedPreferences
final SharedPreferences prefs = await SharedPreferences.getInstance();
return runApp(ProviderScope(
// override SharedPreferences provider with correct value
overrides: [
sharedPreferencesProvider.overrideWithValue(prefs),
],
child: MyApp(),
));
}
Next:
class MyApp extends ConsumerWidget {
// using const we reduce unnecessary rebuild widget
final Widget _myHomePage = const MyHomePage();
@override
Widget build(BuildContext context, WidgetRef ref) {
print(MyApp);
// ref.watch allows you to monitor changes and rebuild our widget if necessary
final bool isDarkMode = ref.watch(appThemeProvider).getTheme();
return MaterialApp(
title: 'Flutter demo',
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
home: _myHomePage,
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage();
@override
Widget build(BuildContext context) {
print(MyHomePage);
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Theme Riverpod Demo'),
),
body: YourListTile(),
);
}
}
Your widget:
class YourListTile extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
print(YourListTile);
final bool isDarkMode = ref.watch(appThemeProvider).getTheme();
return SwitchListTile(
value: isDarkMode,
onChanged: (_) {
// the use of ref.read is necessary in callbacks
ref.read(appThemeProvider.notifier).setTheme(!isDarkMode);
},
secondary: isDarkMode
? const Icon(Icons.dark_mode)
: const Icon(Icons.light_mode),
title: isDarkMode
? const Text(
"Dark Mode",
style: TextStyle(
fontFamily: "Lato",
),
)
: const Text(
"Light Mode",
style: TextStyle(
fontFamily: "Lato",
),
),
);
}
}
Learn more about packages here:
Upvotes: 7
Reputation: 472
I wrote an article about this in particular. Parts of it are out of date and it covers more than your question, but the short answer is: save it locally and include an option to use the system choice if you can (Light/Dark/System).
I recommend using the shared preferences package. It's a flutter favorite and kept up to date.
To save the user choice, have an async method listen for the user switching the theme and update the preference.
Future<void> saveUserTheme(String chosenTheme) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('UserTheme', chosenTheme);
}
On startup, you can load the choice before starting the app asynchronously:
Future<String> getTheme() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('UserTheme') ?? 'default;
}
Upvotes: 2