setState() 的颤振更新状态问题

阿卜杜拉赫曼·阿德尔

我正在尝试从开关小部件更改主题。

但没有任何效果我没有错误,但没有预期的结果

.

它在进行热重载时按预期完美运行

当开关打开并热加载时切换到黑暗主题

当开关关闭并热加载时切换到浅色主题

这是要查看的代码

import 'package:flutter/material.dart';

mixin Th {
  static ThemeMode themeMode = ThemeMode.dark;
  static ThemeData themeData = ThemeData.dark();
  static bool isDark = false;
}

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  static String title = 'Hello Flutter';
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
      title: MyApp.title,
      themeMode: Th.themeMode,
      darkTheme: Th.themeData,
    );
  }
}

class MyHomePage extends StatefulWidget {
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(MyApp.title),
        actions: [
          Switch(
            value: Th.isDark,
            onChanged: (newValue) {
              return setState(
                () {
                  if (!newValue) {
                    Th.themeMode = ThemeMode.light;
                    Th.themeData = ThemeData.light();
                    Th.isDark = newValue;
                    print('Is Dark = ${Th.isDark}');
                  } else if (newValue) {
                    Th.themeMode = ThemeMode.dark;
                    Th.themeData = ThemeData.dark();
                    Th.isDark = newValue;
                    print('Is Dark = ${Th.isDark}');
                  }
                },
              );
            },
          ),
        ],
      ),
    );
  }
}

在控制台打印运行预期结果

这里有什么问题?并感谢您的阅读。

在桌面“Windows 应用程序”的颤振和移动“安卓应用程序”的颤振上进行测试

迪帕克·洛莫德

The reason is that setState only changes the UI of that page only,由于您在 Material 应用程序中定义了主题,因此您需要使用提供程序包在整个应用程序 UI 中进行更改。

首先创建一个 dart 文件来通知听众有关主题的信息,并将以下代码放入其中:-

import 'package:flutter/material.dart';

class ThemeNotifier with ChangeNotifier {
  ThemeData _themeData;

  ThemeNotifier(this._themeData);

  getTheme() => _themeData; // to get current theme of the app

  setTheme(ThemeData themeData) async {
    _themeData = themeData;
    notifyListeners(); // to update the theme of the app
  }
}

在 pubspec.yaml 文件中添加Shared prefs插件

现在,让我们处理 void main。因此,如果您在数据库中没有当前主题/模式的任何值,让我们创建一个函数来获取设备的当前主题。例如,如果用户刚刚安装了应用程序,那么您不知道用户的主题选择,那么如果您提供基于用户移动主题的主题,那就太好了。

getSystemTheme()
  {
    var brightness = SchedulerBinding.instance.window.platformBrightness;
    bool darkModeOn = brightness == Brightness.dark;
    return darkModeOn;
  }

以上函数将返回布尔值,无论深色主题是打开还是关闭

现在让我们从本地数据库中获取值并相应地提供主题。

SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values).then((_) {
    SharedPreferences.getInstance().then((prefs) {
      var darkModeOn = prefs.getBool('isDarkTheme') ?? getSystemTheme(); //if have value in database then that theme else the system theme will be used
      runApp(
        ChangeNotifierProvider<ThemeNotifier>(
          create: (_) => ThemeNotifier(darkModeOn ? MyThemes.darktheme : MyThemes.lightTheme),
          child: MyApp(),
        ),
      );
    });
  });

现在 MyApp() 小部件的代码:-

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final themeNotifier = Provider.of<ThemeNotifier>(context);
    return Consumer<ThemeNotifier>(
      builder: (context, appState, child) {
        return MaterialApp(
          theme: themeNotifier.getTheme(),
          home: HomeScreen(),
        );
      },
    );
  }
}

如果您想让您的用户选择手动更改主题,那么您可以为其创建一个开关并执行以下更新以动态更改主题(无需重新启动应用程序)。:-

    class Settings extends StatefulWidget {
    
      @override
      _SettingsState createState() => _SettingsState();
    }
    
    class _SettingsState extends State<Settings> {
      bool _darkTheme=false;

      void toggleSwitch(bool value, ThemeNotifier themeNotifier) async {
    (value)
        ? themeNotifier.setTheme(AppTheme.darktheme)
        : themeNotifier.setTheme(AppTheme.lighttheme);//here change of theme will take place
        var prefs = await SharedPreferences.getInstance();
        prefs.setBool('isDarkTheme', value); // and this code will save the boolean value whether darkmode is on or off to the local storage.
      }

      @override
      Widget build(BuildContext context) {
        final themeNotifier = Provider.of<ThemeNotifier>(context);
        _darkTheme = (themeNotifier.getTheme() == MyThemes.darktheme);

        return Scaffold(
            body: Row(
               mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Expanded(child: Text("Dark Mode",style: TextStyle(fontSize: 18),)),
                Switch(
                  value: _darkTheme,
                  onChanged: (val) {
                    setState(() {
                      _darkTheme = val;
                    });
                    toggleSwitch(val, themeNotifier);
                  },
                ),
              ],
            )
         );
      }
    }

PS:-您可以删除共享首选项,但要存储用户选择的主题的值,以便每当他/她重新启动应用程序时都会维护主题,您应该添加它..

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章