【问题标题】:Flutter : Change Theme Brightness from another WidgetFlutter:从另一个小部件更改主题亮度
【发布时间】:2020-04-15 21:33:38
【问题描述】:

我有 2 个屏幕 LoginHome 来学习 MaterialApp 动态中的亮度变化。我使用 2 个包 HiveProvider Packages 来帮助我处理我的案子。

一切都很好,我可以在 主屏幕 中更改值开关,但问题是 MaterialApp 中的值没有更改。我只看到开关改变但 ThemeData 没有改变。如果我热重启它就改变了。

我搞错了什么?

用户提供者

class UserProvider with ChangeNotifier {
  final String boxName = "user_box";
  Future<void> changeThemeApp({@required UserModelHive userModelHive}) async {
    final hiveBox = Hive.box(boxName);
    final valueBox = userModelHive;
    await hiveBox.put("userSession", valueBox);
    notifyListeners();
  }
}

MyApp 小部件

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final appDir = await pathProvider.getApplicationDocumentsDirectory();
  Hive.init(appDir.path);
  Hive.registerAdapter(UserModelHiveAdapter(), 0);
  await Hive.openBox('user_box');
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final userBox = Hive.box('user_box');
    if (userBox.isEmpty) {
      return MaterialAppCustom(home: LoginProvider());
    } else {
      final UserModelHive userModelHive = userBox.get("userSession");
      print(userModelHive.isDarkMode.toString());
      return MaterialAppCustom(
        brightness:
            userModelHive.isDarkMode ? Brightness.dark : Brightness.light,
        home: HomeScreen(),
      );
    }
  }
}

class MaterialAppCustom extends StatelessWidget {
  final Widget home;
  final Brightness brightness;
  MaterialAppCustom({@required this.home, this.brightness});
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => UserProvider(),
      child: MaterialApp(
        home: home,
        theme: ThemeData(brightness: brightness),
        routes: {
          LoginProvider.routeNamed: (ctx) => LoginProvider(),
          HomeScreen.routeNamed: (ctx) => HomeScreen(),
        },
      ),
    );
  }
}

主屏幕

class HomeScreen extends StatelessWidget {
  static const routeNamed = "home-screen";
  @override
  Widget build(BuildContext context) {
    final userProvider = Provider.of<UserProvider>(context);
    final UserModelHive userModelHive = Hive.box('user_box').get("userSession");
    return Scaffold(
      body: AppBar(
        actions: <Widget>[
          Switch(
            value: userModelHive.isDarkMode,
            onChanged: (value) {
              return userProvider.changeThemeApp(
                userModelHive: UserModelHive()
                  ..id = userModelHive.id
                  ..name = userModelHive.name
                  ..isDarkMode = value,
              );
            },
          ),
        ],
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart


    【解决方案1】:
    1. WatchBoxBuilder 小部件包裹你的MaterialApp(它在hive 包中)。
    2. 您应该使用枚举、整数或字符串值映射您的主题。
    3. 有一个 Hive 框,您可以在其中保存主题的值。
    4. 将该框交给包裹在 Material Widget 周围的 WatchBoxBuilder
    5. 现在,只要在 hive 框中更改主题的值,您的 WatchBoxBuilder 就会重新构建,并且您的主题将从应用的任何部分更改。

    当您在小部件树中使用 hive 时,您应该只通过 WatchBoxBuilder 读取值。它具有重建小部件的能力,以便它可以使用新值。

    希望对你有帮助,如有疑问请评论。

    【讨论】:

    • 明白了!是工作。但是如果我已经在使用 hive 我很有趣,提供程序中的 notifylistiner 没用吗?因为我只是用 WatchboxBuilder 包装小部件来重建小部件。
    • 如果您使用 Hive,则不需要 notifyListener。
    猜你喜欢
    • 2022-06-30
    • 1970-01-01
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 2021-07-20
    相关资源
    最近更新 更多