-
-
Save RodBr/37310335c6639f486bb3c8a628052405 to your computer and use it in GitHub Desktop.
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:get/get.dart'; | |
import 'package:shared_preferences/shared_preferences.dart'; //STEP 4 - Import shared_preferences | |
void main() { | |
Get.lazyPut<ThemeController>( | |
() => ThemeController()); //STEP 5 - lazy create ThemeController | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
ThemeController.to | |
.getThemeModeFromPreferences(); //STEP 6 - Get saved theme at startup | |
return GetMaterialApp( | |
title: 'Theme change using Get', | |
theme: ThemeData.light().copyWith(primaryColor: Colors.green), | |
darkTheme: ThemeData.dark().copyWith(primaryColor: Colors.purple), | |
themeMode: ThemeMode.system, | |
home: MyHomePage(), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
MyHomePage({Key key}) : super(key: key); | |
@override | |
_MyHomePageState createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
ThemeMode _themeMode; | |
@override | |
Widget build(BuildContext context) { | |
_themeMode = ThemeController | |
.to.themeMode; //STEP 7 - get the theme from ThemeController | |
print('${MediaQuery.of(context).platformBrightness}'); | |
print('${Theme.of(context).brightness}'); | |
return Scaffold( | |
appBar: AppBar(), | |
body: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: <Widget>[ | |
Center( | |
child: Text( | |
'System Brightness: ${Get.mediaQuery.platformBrightness.toString()}', | |
style: TextStyle(fontSize: 20), | |
), | |
), | |
SizedBox(height: 24), | |
Center( | |
child: Text( | |
'Theme Brightness: ${Get.theme.brightness.toString()}', | |
style: TextStyle(fontSize: 20), | |
), | |
), | |
SizedBox(height: 24), | |
Text( | |
'ThemeMode', | |
style: TextStyle(fontSize: 20), | |
textAlign: TextAlign.left, | |
), | |
RadioListTile( | |
title: Text('system'), | |
value: ThemeMode.system, | |
groupValue: _themeMode, | |
onChanged: (value) { | |
setState(() { | |
_themeMode = value; | |
ThemeController.to | |
.setThemeMode(_themeMode); //STEP 8 - change this line | |
}); | |
}, | |
), | |
RadioListTile( | |
title: Text('dark'), | |
value: ThemeMode.dark, | |
groupValue: _themeMode, | |
onChanged: (value) { | |
setState(() { | |
_themeMode = value; | |
ThemeController.to.setThemeMode(_themeMode); | |
}); | |
}, | |
), | |
RadioListTile( | |
title: Text('light'), | |
value: ThemeMode.light, | |
groupValue: _themeMode, | |
onChanged: (value) { | |
setState(() { | |
_themeMode = value; | |
ThemeController.to.setThemeMode(_themeMode); | |
}); | |
}, | |
), | |
], | |
), | |
); | |
} | |
} | |
//STEP 9 - add our ThemeController | |
class ThemeController extends GetController { | |
static ThemeController get to => Get.find(); | |
SharedPreferences prefs; | |
ThemeMode _themeMode; | |
ThemeMode get themeMode => _themeMode; | |
Future<void> setThemeMode(ThemeMode themeMode) async { | |
Get.changeThemeMode(themeMode); | |
_themeMode = themeMode; | |
update(); | |
prefs = await SharedPreferences.getInstance(); | |
await prefs.setString('theme', themeMode.toString().split('.')[1]); | |
} | |
getThemeModeFromPreferences() async { | |
ThemeMode themeMode; | |
prefs = await SharedPreferences.getInstance(); | |
String themeText = prefs.getString('theme') ?? 'system'; | |
try { | |
themeMode = | |
ThemeMode.values.firstWhere((e) => describeEnum(e) == themeText); | |
} catch (e) { | |
themeMode = ThemeMode.system; | |
} | |
setThemeMode(themeMode); | |
} | |
} |
That's awesome and so simple!
I do have one issue though - I have a settings route, changing the theme here does change the theme for the app and the option (radio) for the chosen theme is selected when you open the settings again. The problem occurs if the app is stopped and restarted (emulator), or after a restart (device). The _themeMode = ThemeController.to.themeMode; in the settings route returns null so no theme is selected in the settings route, although the app does use the theme that was last selected.
Main.dart:
`void main() {
Get.lazyPut(() => ThemeController()); //STEP 5 - lazy create ThemeController
ThemeController.to.getThemeModeFromPreferences(); //STEP 6 - Get saved theme at startup
runApp(GetMaterialApp(
translations: ClsText(),
locale: Get.deviceLocale,
debugShowCheckedModeBanner: false,
title: 'app name',
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeController.to.themeMode,`
Settingsroute:
`class _SettingsRouteState extends State {
ThemeMode _themeMode;
@OverRide
Widget build(BuildContext context) {
// get current theme mode
_themeMode = ThemeController.to.themeMode; // initially returns null so no radio is selected
1 of the 3 Radios on settings route (all 3 the same except the value):
new Radio(
value: ThemeMode.system,
groupValue: _themeMode,
onChanged: (value) {
setState(() {
_themeMode = value;
ThemeController.to
.setThemeMode(_themeMode); //STEP 8 - change this line
});
},
),`
What am I missing? Please help
UPDATE: I didn't resolve this but I did simplify the settings option. I changed it to a Dark Mode on/off switch;
var _brightness = Theme.of(context).brightness; bool _darkModeOn = _brightness == Brightness.dark;
would be nice to have 3 options though
The following LateError was thrown building MyApp(dirty):
LateInitializationError: Field '_themeMode' has not been initialized.
The relevant error-causing widget was:
MyApp
lib\main.dart:9
When the exception was thrown, this was the stack:
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw
packages/getx_theme/main.dart 115:18 get [_themeMode]
Launching lib\main.dart on Chrome in debug mode...
lib\main.dart:1
This app is linked to the debug service: ws://127.0.0.1:63230/_nWvV3Z8uCw=/ws
Debug service listening on ws://127.0.0.1:63230/_nWvV3Z8uCw=/ws
Running with sound null safety
Connecting to VM Service at ws://127.0.0.1:63230/_nWvV3Z8uCw=/ws
Flutter Web Bootstrap: Programmatic
packages/getx_theme/main.dart 116:30 get themeMode
packages/getx_theme/main.dart 23:37 build
packages/flutter/src/widgets/framework.dart 4949:22 build
packages/flutter/src/widgets/framework.dart 4878:15 performRebuild
packages/flutter/src/widgets/framework.dart 4604:5 rebuild
packages/flutter/src/widgets/framework.dart 4859:5 [_firstBuild]
packages/flutter/src/widgets/framework.dart 4853:5 mount
packages/flutter/src/widgets/framework.dart 3863:15 inflateWidget
packages/flutter/src/widgets/framework.dart 3592:18 updateChild
packages/flutter/src/widgets/binding.dart 1195:16 [_rebuild]
packages/flutter/src/widgets/binding.dart 1164:5 mount
packages/flutter/src/widgets/binding.dart 1111:16
packages/flutter/src/widgets/framework.dart 2605:19 buildScope
packages/flutter/src/widgets/binding.dart 1110:12 attachToRenderTree
packages/flutter/src/widgets/binding.dart 944:24 attachRootWidget
packages/flutter/src/widgets/binding.dart 925:7
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19 internalCallback
Line Number 21 should be changed to:
themeMode: ThemeController.to.themeMode,