J'ai un MaterialApp
avec un ThemeData
qui est initialement défini sur Brightness.light
. J'aimerais changer la luminosité sur Brightness.dark
au moment de l'exécution, mais lorsque j'effectue cette modification, seule la barre d'état change - aucun des widgets Flutter ne modifie réellement sa luminosité.
Comment peut ce comportement est-il atteint?
Pour modifier le ThemeData
au moment de l'exécution, j'ai créé le StatefulWidget
suivant qui encapsule mon code MaterialApp > et le reconstruit chaque fois que le thème change:
final ThemeData appTheme = ThemeData( brightness: Brightness.light, ); class ThemeChanger extends StatefulWidget { static ThemeChangerState of (BuildContext context) { return context.ancestorStateOfType(TypeMatcher<ThemeChangerState>()); } ThemeChanger({ this.childBuilder, }); final Widget Function(BuildContext, ThemeData) childBuilder; @override ThemeChangerState createState() => ThemeChangerState(); } class ThemeChangerState extends State<ThemeChanger> { Brightness _brightness = Brightness.light; set brightness(Brightness brightness) { setState(() { _brightness = brightness; }); } @override Widget build(BuildContext context) { return widget.childBuilder( context, appTheme.copyWith( brightness: _brightness ), ); } } // Then in main.dart void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return DemoTheme( childBuilder: (BuildContext context, ThemeData theme) { return MaterialApp( title: 'Materially Better', theme: theme, routes: { '/': (BuildContext context) { return LoginScreen(); }, 'home': (BuildContext context) { return MainScreen(); } }, debugShowCheckedModeBanner: false, ); }, ); } }
4 Réponses :
Le problème est que ThemeData
utilise sa valeur de luminosité
dans le constructeur pour synthétiser un certain nombre d'autres couleurs, mais ces couleurs ne sont pas recalculées lorsque ThemeData
est muté. Par conséquent, la solution est d'instancier un tout nouveau ThemeData
plutôt que d'utiliser appTheme.copyWith (...)
.
Modifiez ceci:
ThemeData( brightness: _brightness, ),
À ceci:
appTheme.copyWith( brightness: _brightness, ),
Vous pouvez consulter la bibliothèque suivante: https://github.com/Norbert515/dynamic_theme
Il vous permet de modifier toutes les données du thème ou la luminosité de votre application de manière dynamique lors de l'exécution.
Vous pouvez changer le thème lors de l'exécution avec ThemeBuilder:
setState(() { ThemeBuilder.of(context).changeTheme(); });
Ma solution est la suivante:
Définissez une variable dans main.dart
pour la luminosité et une fonction qui change l'état.
Transmettez la fonction à une classe et appelez-la là où vous en avez besoin.
darkModeChanged(bool newValue) { Preferences.setBool('darkMode', newValue); setState(() { _darkMode = newValue; Util.currentBrightness = _darkMode ? Brightness.dark : Brightness.light; Util.changeBrightness(Util.currentBrightness); }); }
Dans la classe Util
class Util { static Brightness currentBrightness = Brightness.light; static Function changeBrightness; // ...further implementations
Et puis appelez-le quand vous en avez besoin. Dans mon cas, un changement de commutateur dans l'écran des paramètres:
//main.dart class _MyAppState extends State<MyApp> { Brightness _brightness = Brightness.light; void _changeBrightness(Brightness newBrightness) { setState(() { _brightness = newBrightness; }); } @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { //PASSING THE FUNCTION AS PARAMETER Util.changeBrightness = _changeBrightness; }); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Your app title', theme: ThemeData( primaryColor: const Color(0xFFb30047), brightness: _brightness, primarySwatch: Colors.blue, accentColor: Colors.white, /// ...and so on