6
votes

Flutter: Comment modifier la luminosité du thème lors de l'exécution?

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,
        );
      },
    );
  }
}


0 commentaires

4 Réponses :


2
votes

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,
),


0 commentaires

1
votes

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.


0 commentaires

1
votes

Vous pouvez changer le thème lors de l'exécution avec ThemeBuilder:

setState(() {
  ThemeBuilder.of(context).changeTheme();
});


0 commentaires

1
votes

Ma solution est la suivante:

  1. Définissez une variable dans main.dart pour la luminosité et une fonction qui change l'état.

  2. 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


0 commentaires