点击手势检测器后,Flutter UI 不会刷新

Flutter UI is not refreshing once tap the gesture detector

我实现了一个介绍屏幕,用户可以在开始时设置应用程序的主题。 一切正常,但我面临的唯一问题是选择时 BoxDecoration 切换颜色。仅当我从浅色模式切换到系统默认值时(当系统默认值处于浅色模式时,它在暗色模式下工作正常)才会出现此问题,反之亦然。而且我在调试时没有遇到任何错误。我还附上了一段视频 link.

https://youtu.be/u9_DWS9v0f8

IntroScreen.dart

import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:mint/helpers/config.dart';
import 'package:mint/ui/animations/showUp.dart';
import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

enum ThemeSelected { System, Light, Dark }

class IntroTheme extends StatefulWidget {
  const IntroTheme({Key? key}) : super(key: key);

  @override
  _IntroThemeState createState() => _IntroThemeState();
}

class _IntroThemeState extends State<IntroTheme> {
  // Currently Selected Theme
  ThemeSelected? theme;
  final MyTheme currentTheme = GetIt.I<MyTheme>();

  @override
  void initState() {
    super.initState();
    theme = ThemeSelected.System;
  }

  @override
  Widget build(BuildContext context) {
    void checkTheme() {
      if (currentTheme.currentTheme() == ThemeMode.system) {
        theme = ThemeSelected.System;
      } else if (currentTheme.currentTheme() == ThemeMode.light) {
        theme = ThemeSelected.Light;
      } else if (currentTheme.currentTheme() == ThemeMode.dark) {
        theme = ThemeSelected.Dark;
      }
    }

    checkTheme();
    return SafeArea(
        child: Stack(
      alignment: Alignment.center,
      children: [
        ShowUpTransition(
          duration: const Duration(milliseconds: 600),
          forward: true,
          slideSide: SlideFromSlide.LEFT,
          child: Align(
            alignment: Alignment.topLeft,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Row(
                children: [
                  const Padding(
                    padding: EdgeInsets.only(right: 8),
                    child: AnimatedSwitcher(
                      duration: Duration(milliseconds: 300),
                      child: Icon(EvaIcons.colorPaletteOutline,
                          size: 40, color: Colors.red),
                    ),
                  ),
                  RichText(
                    textAlign: TextAlign.center,
                    text: TextSpan(
                        style: TextStyle(
                            fontSize: 22,
                            fontFamily: 'Product Sans',
                            fontWeight: FontWeight.w600,
                            color:
                                Theme.of(context).textTheme.bodyText1?.color),
                        children: [
                          const TextSpan(text: "App "),
                          TextSpan(
                              text: AppLocalizations.of(context)!
                                  .intro_labelAppCustomization,
                              style: TextStyle(
                                  color:
                                      Theme.of(context).colorScheme.secondary,
                                  fontWeight: FontWeight.w600))
                        ]),
                  ),
                ],
              ),
            ),
          ),
        ),
        ShowUpTransition(
          slideSide: SlideFromSlide.BOTTOM,
          duration: const Duration(milliseconds: 600),
          forward: true,
          child: SizedBox(
            width: MediaQuery.of(context).size.width * 0.6,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Image.asset(
                  'assets/images/appTheme.png',
                  fit: BoxFit.contain,
                  height: 300.0,
                  width: 300.0,
                ),
                Container(
                  margin: const EdgeInsets.only(top: 32),
                  child: RichText(
                    textAlign: TextAlign.center,
                    text: TextSpan(
                        style: TextStyle(
                            fontSize: 18,
                            fontFamily: 'Product Sans',
                            fontWeight: FontWeight.w500,
                            color:
                                Theme.of(context).textTheme.bodyText1?.color),
                        children: [
                          TextSpan(
                              text: AppLocalizations.of(
                                    context,
                                  )!
                                      .intro_labelSelectPreferred +
                                  "\n"),
                          TextSpan(
                              text: AppLocalizations.of(
                                    context,
                                  )!
                                      .intro_labelTheme +
                                  "!",
                              style: TextStyle(
                                  color:
                                      Theme.of(context).colorScheme.secondary,
                                  fontWeight: FontWeight.w600))
                        ]),
                  ),
                ),
              ],
            ),
          ),
        ),
        Container(
          alignment: Alignment.bottomCenter,
          margin: const EdgeInsets.only(bottom: 32),
          child: Flex(
            direction: Axis.horizontal,
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Flexible(
                flex: 1,
                child: Padding(
                  padding: const EdgeInsets.only(left: 30, right: 15),
                  child: ShowUpTransition(
                    duration: const Duration(milliseconds: 600),
                    delay: const Duration(milliseconds: 600),
                    forward: true,
                    slideSide: SlideFromSlide.BOTTOM,
                    child: GestureDetector(
                      onTap: () {
                        currentTheme.switchTheme(
                          isDark: false,
                          useSystemTheme: true,
                        );
                      },
                      child: AnimatedContainer(
                        padding: const EdgeInsets.all(8),
                        duration: const Duration(milliseconds: 150),
                        height: 50,
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(20),
                            color: theme == ThemeSelected.System
                                ? Theme.of(context).colorScheme.secondary
                                : Theme.of(context).cardColor.withOpacity(0.4),
                            boxShadow: [
                              BoxShadow(
                                  color: Colors.black12.withOpacity(0.08),
                                  offset: const Offset(0, 0),
                                  spreadRadius: 0.01,
                                  blurRadius: 20.0)
                            ]),
                        child: Center(
                          child: Text(
                              AppLocalizations.of(
                                context,
                              )!
                                  .intro_labelSystem,
                              style: TextStyle(
                                  fontSize: 14,
                                  color: theme == ThemeSelected.System
                                      ? Colors.white
                                      : Theme.of(context)
                                          .textTheme
                                          .bodyText1
                                          ?.color,
                                  fontWeight: FontWeight.w700,
                                  fontFamily: 'Product Sans')),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
              Flexible(
                flex: 1,
                child: Padding(
                  padding: const EdgeInsets.only(left: 15, right: 15),
                  child: ShowUpTransition(
                    duration: const Duration(milliseconds: 600),
                    delay: const Duration(milliseconds: 700),
                    forward: true,
                    slideSide: SlideFromSlide.BOTTOM,
                    child: GestureDetector(
                      onTap: () {
                        currentTheme.switchTheme(
                          isDark: false,
                          useSystemTheme: false,
                        );
                      },
                      child: AnimatedContainer(
                        padding: const EdgeInsets.all(8),
                        duration: const Duration(milliseconds: 150),
                        height: 50,
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(20),
                            color: theme == ThemeSelected.Light
                                ? Theme.of(context).colorScheme.secondary
                                : Theme.of(context).cardColor.withOpacity(0.4),
                            boxShadow: [
                              BoxShadow(
                                  color: Colors.black12.withOpacity(0.08),
                                  offset: const Offset(0, 0),
                                  spreadRadius: 0.01,
                                  blurRadius: 20.0)
                            ]),
                        child: Center(
                          child: Text("Light",
                              style: TextStyle(
                                  fontSize: 14,
                                  color: theme == ThemeSelected.Light
                                      ? Colors.white
                                      : Theme.of(context)
                                          .textTheme
                                          .bodyText1
                                          ?.color,
                                  fontWeight: FontWeight.w700,
                                  fontFamily: 'Product Sans')),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
              Flexible(
                flex: 1,
                child: Padding(
                  padding: const EdgeInsets.only(left: 15, right: 30),
                  child: ShowUpTransition(
                    duration: const Duration(milliseconds: 600),
                    delay: const Duration(milliseconds: 800),
                    forward: true,
                    slideSide: SlideFromSlide.BOTTOM,
                    child: GestureDetector(
                      onTap: () {
                        currentTheme.switchTheme(
                          isDark: true,
                          useSystemTheme: false,
                        );
                      },
                      child: AnimatedContainer(
                        padding: const EdgeInsets.all(8),
                        duration: const Duration(milliseconds: 150),
                        height: 50,
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(20),
                            color: theme == ThemeSelected.Dark
                                ? Theme.of(context).colorScheme.secondary
                                : Theme.of(context).cardColor.withOpacity(0.4),
                            boxShadow: [
                              BoxShadow(
                                  color: Colors.black12.withOpacity(0.08),
                                  offset: const Offset(0, 0),
                                  spreadRadius: 0.01,
                                  blurRadius: 20.0)
                            ]),
                        child: Center(
                          child: Text("Dark",
                              style: TextStyle(
                                  fontSize: 14,
                                  color: theme == ThemeSelected.Dark
                                      ? Colors.white
                                      : Theme.of(context)
                                          .textTheme
                                          .bodyText1
                                          ?.color,
                                  fontWeight: FontWeight.w700,
                                  fontFamily: 'Product Sans')),
                        ),
                      ),
                    ),
                  ),
                ),
              )
            ],
          ),
        )
      ],
    ));
  }
}

config.dart

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';

class MyTheme with ChangeNotifier {
  bool _isDark =
      Hive.box('settings').get('darkMode', defaultValue: false) as bool;

  bool _useSystemTheme =
      Hive.box('settings').get('useSystemTheme', defaultValue: false) as bool;

  
  void refresh() {
    final Box settingsBox = Hive.box('settings');
    _isDark = settingsBox.get('darkMode', defaultValue: true) as bool;

    _useSystemTheme =
        settingsBox.get('useSystemTheme', defaultValue: false) as bool;

    accentColor = settingsBox.get('themeColor', defaultValue: 'Teal') as String;
    canvasColor =
        settingsBox.get('canvasColor', defaultValue: 'Grey') as String;
    cardColor = settingsBox.get('cardColor', defaultValue: 'Grey900') as String;

    backGrad = settingsBox.get('backGrad', defaultValue: 2) as int;
    cardGrad = settingsBox.get('cardGrad', defaultValue: 4) as int;
    bottomGrad = settingsBox.get('bottomGrad', defaultValue: 3) as int;

    colorHue = settingsBox.get('colorHue', defaultValue: 400) as int;
    notifyListeners();
  }

  void switchTheme({bool? useSystemTheme, bool? isDark, bool notify = true}) {
    if (isDark != null) {
      _isDark = isDark;
    }
    if (useSystemTheme != null) {
      _useSystemTheme = useSystemTheme;
    }
    Hive.box('settings').put('darkMode', _isDark);
    Hive.box('settings').put('useSystemTheme', _useSystemTheme);
    if (notify) notifyListeners();
  }

  ThemeMode currentTheme() {
    if (_useSystemTheme == true) {
      return ThemeMode.system;
    } else {
      return _isDark ? ThemeMode.dark : ThemeMode.light;
    }
  }

  Color currentColor() {
    switch (accentColor) {
      case 'Red':
        return Colors.redAccent[currentHue()]!;
      case 'Teal':
        return Colors.tealAccent[currentHue()]!;
      case 'Light Blue':
        return Colors.lightBlueAccent[currentHue()]!;
      case 'Yellow':
        return Colors.yellowAccent[currentHue()]!;
      case 'Orange':
        return Colors.orangeAccent[currentHue()]!;
      case 'Blue':
        return Colors.blueAccent[currentHue()]!;
      case 'Cyan':
        return Colors.cyanAccent[currentHue()]!;
      case 'Lime':
        return Colors.limeAccent[currentHue()]!;
      case 'Pink':
        return Colors.pinkAccent[currentHue()]!;
      case 'Green':
        return Colors.greenAccent[currentHue()]!;
      case 'Amber':
        return Colors.amberAccent[currentHue()]!;
      case 'Indigo':
        return Colors.indigoAccent[currentHue()]!;
      case 'Purple':
        return Colors.purpleAccent[currentHue()]!;
      case 'Deep Orange':
        return Colors.deepOrangeAccent[currentHue()]!;
      case 'Deep Purple':
        return Colors.deepPurpleAccent[currentHue()]!;
      case 'Light Green':
        return Colors.lightGreenAccent[currentHue()]!;
      case 'White':
        return Colors.white;

      default:
        return _isDark ? Colors.tealAccent[400]! : Colors.lightBlueAccent[400]!;
    }
  }

  void setInitialTheme(String themeName) {
    Hive.box('settings').put('theme', themeName);
  }

  String getInitialTheme() {
    return Hive.box('settings').get('theme') as String;
  }
}

提前致谢。

使用 setState 在 GestureDetector

中更新您的 UI
onTap() {       
setState(() {
           currentTheme.switchTheme(
            isDark: false,
             useSystemTheme: true,
           );
       });
}

希望有用