Reputation: 1630
Here I've one screen where I've some button when I press the button it will change the color of application but it will reset when I restart the app. I want that it will not reset until I am changing the color from the App. so for that, I want to store THemedata in shared preferences and I want to get theme data from shared preferences so whenever I restart the app it needs to take the theme from Shared preferences.
Here is some code I've tried,
ThemeBloc.dart
class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
@override
ThemeState get initialState =>
ThemeState(themeData: appThemeData[AppTheme.GreenLight]);
@override
Stream<ThemeState> mapEventToState(
ThemeEvent event,
) async* {
if (event is ThemeChanged) {
yield ThemeState(themeData: appThemeData[event.theme]);
}
}
}
ThemeEvent.dart
abstract class ThemeEvent extends Equatable {
ThemeEvent([List props = const <dynamic>[]]) : super(props);
}
class ThemeChanged extends ThemeEvent {
final AppTheme theme;
ThemeChanged({
this.theme,
}) : super([theme]);
}
ThemeState.dart
@immutable
class ThemeState extends Equatable {
final ThemeData themeData;
ThemeState({
@required this.themeData,
}) : super([themeData]);
}
AppTheme.dart
enum AppTheme {
GreenLight,
GreenDark,
BlueLight,
BlueGrey,
Amber,
}
final appThemeData = {
AppTheme.GreenLight: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.teal,
),
AppTheme.GreenDark: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.orange,
),
};
Upvotes: 1
Views: 4720
Reputation: 225
Use ThemeProvider for providing themes data. There is an example. For detailed information, you can run this app from this GitHub
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
ThemeData light_mode = ThemeData(
brightness: Brightness.light,
);
ThemeData dark_mode = ThemeData(
brightness: Brightness.dark,
);
class ThemeNotifier extends ChangeNotifier {
final String key = "theme";
SharedPreferences? _preferences;
bool? _darkMode;
bool? get darkMode => _darkMode;
ThemeNotifier() {
_darkMode = false;
_loadFromPreferences();
}
_initialPreferences() async {
_preferences ??= await SharedPreferences.getInstance();
}
_savePreferences() async {
await _initialPreferences();
_preferences!.setBool(key, _darkMode!);
}
_loadFromPreferences() async {
await _initialPreferences();
_darkMode = _preferences!.getBool(key) ?? true;
notifyListeners();
}
toggleChangeTheme(bool isOn) {
darkMode==isOn ? _darkMode! : _darkMode = !_darkMode!;
_savePreferences();
notifyListeners();
}
}
Upvotes: 1
Reputation: 21
// Your AppTheme.dart
enum AppTheme {
GreenLight,
GreenDark,
BlueLight,
BlueGrey,
Amber,
}
final appThemeData = {
AppTheme.GreenLight: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.teal,
),
AppTheme.GreenDark: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.orange,
),
};
// shared_prefs.dart
class SharedPrefs {
static late SharedPreferences _sharedPrefs;
factory SharedPrefs() => SharedPrefs._internal();
SharedPrefs._internal();
Future<void> init() async {
_sharedPrefs = await SharedPreferences.getInstance();
}
int? get getThemeIndex => _sharedPrefs.getInt(selectedThemeIndex);
set setThemeIndex(int? value) {
_sharedPrefs.setInt(selectedThemeIndex, value!); // Using selectedThemeIndex from constant
}
}
// constants.dart
const String selectedThemeIndex = "selected_theme_index";
// main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SharedPrefs().init(); // Call sharedpreference class here
return runApp(MyApp());
}
//theme_bloc.dart
class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
ThemeBloc() : super(ThemeState(themeData: appThemeData[AppTheme.values[SharedPrefs().getThemeIndex ?? 0]]!));
@override
Stream<ThemeState> mapEventToState(
ThemeEvent event,
) async* {
if (event is ThemeChanged) {
// I am storing theme index
SharedPrefs().setThemeIndex = event.theme.index; // Trigger when you change the theme
yield ThemeState(themeData: appThemeData[event.theme]!);
}
}
}
Upvotes: 0
Reputation: 740
You can simply save/retrieve a theme id that can be used to identify wich theme is selected when starting the app, something like
class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
// at this point you should be already have a mainSharedPreferences already initialized, could be in SplashScreen
// to prevent async calls in the initialState
@override
ThemeState get initialState => ThemeState(
themeData: appThemeData[
MyApp.mainSharedPreferences.getInt("selectedThemeIndex") ??
AppTheme.GreenLight]);
@override
Stream<ThemeState> mapEventToState(
ThemeEvent event,
) async* {
if (event is ThemeChanged) {
await _persistTheme(event.theme);
yield ThemeState(themeData: appThemeData[event.theme]);
}
}
_persistTheme(AppTheme theme) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt("selectedThemeIndex", theme.index);
// or you could save the theme.toString()
// prefs.setString("selectedTheme", theme.toString());
}
}
How to prepare SharedPreferences to avoid the Future<SharedPreferences>
class MyApp extends StatefulWidget {
static SharedPreferences mainSharedPreferences;
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
_loadApp() async {
MyApp.mainSharedPreferences = await SharedPreferences.getInstance();
// you can load here any other data or external data that your app might need
}
@override
void initState() {
super.initState();
_loadApp();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: [
// ...
Then you can use it anywhere from your app like so
// to save value
MyApp.mainSharedPreferences.setInt("selectedThemeIndex", value);
// to get the saved value
MyApp.mainSharedPreferences.getInt("selectedThemeIndex");
Upvotes: 3