dart - Flutter 动态主题

标签 dart flutter

动态更改 Flutter 应用主题的最佳方式是什么?例如,如果用户将颜色更改为红色,我希望主题立即更改为红色。除了一个人说使用我不熟悉的 BLOC 模式外,我在网上找不到任何有用的东西。我想听听你们对这个问题的看法。谢谢!

我目前的代码结构:

var themeData = ThemeData(
    fontFamily: 'Raleway',
    primaryColor: Colors.blue,
    brightness: Brightness.light,
    backgroundColor: Colors.white,
    accentColor: Colors.blue);

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: Constants.appName,
      theme: themeData,
      home: CheckAuth(), //CheckAuth returns MyHomePage usually
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title, @required this.uid}) : super(key: key);

  final String title;
  final String uid;

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

class _MyHomePageState extends State<MyHomePage> {
    ...build and stuff
    }

最佳答案

您可以使用 InhertedWidget如果您愿意(而不是 BLOC)- 基本上它用于访问树中任何位置的父小部件。

那么你应该做的是

  1. 创建 InheritedWidget,在树顶部的某个地方 [从您希望主题效果发生的地方]
  2. 将它包裹在 Theme 小部件上
  3. 通过传递要替换的 ThemeData 来公开切换主题的方法。

这是一些代码:

import 'package:flutter/material.dart';

var themeData = ThemeData(
    fontFamily: 'Raleway',
    primaryColor: Colors.blue,
    brightness: Brightness.light,
    backgroundColor: Colors.white,
    accentColor: Colors.blue
);

void main() {
  runApp(
    ThemeSwitcherWidget(
      initialTheme: themeData,
      child: MyApp(),
    ),
  );
}

class ThemeSwitcher extends InheritedWidget {
  final _ThemeSwitcherWidgetState data;

  const ThemeSwitcher({
    Key key,
    @required this.data,
    @required Widget child,
  })  : assert(child != null),
        super(key: key, child: child);

  static _ThemeSwitcherWidgetState of(BuildContext context) {
    return (context. dependOnInheritedWidgetOfExactType(ThemeSwitcher)
            as ThemeSwitcher)
        .data;
  }

  @override
  bool updateShouldNotify(ThemeSwitcher old) {
    return this != old;
  }
}

class ThemeSwitcherWidget extends StatefulWidget {
  final ThemeData initialTheme;
  final Widget child;

  ThemeSwitcherWidget({Key key, this.initialTheme, this.child})
      : assert(initialTheme != null),
        assert(child != null),
        super(key: key);

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

class _ThemeSwitcherWidgetState extends State<ThemeSwitcherWidget> {
  ThemeData themeData;

  void switchTheme(ThemeData theme) {
    setState(() {
      themeData = theme;
    });
  }

  @override
  Widget build(BuildContext context) {
    themeData = themeData ?? widget.initialTheme;
    return ThemeSwitcher(
      data: this,
      child: widget.child,
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeSwitcher.of(context).themeData,
      home: CheckAuth(),
    );
  }
}

我已将 ThemeSwitcherWidget 包裹在 MaterialApp 周围,因此效果遍及整个应用程序(即使您使用 Navigator 推送新路线)。

在 ThemeSwithcerWidget 下方的任何位置使用 ThemeSwitcher.of(context).switchTheme(themeData) 来更改主题。

在有问题的情况下,它应该调用 ThemeSwitcher.of(context).switchTheme(Theme.of(context).copyWith(primaryColor: Colors.red)) 将原色切换为红色应用程序,例如。在某些按钮上单击

编辑:替换了 inheritFromWidgetOfExactType -> dependOnInheritedWidgetOfExactType,因为它已被弃用 - 正如 Phoca 所指出的在评论中。

关于dart - Flutter 动态主题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54757480/

相关文章:

flutter - 每次切换屏幕时,Flutter Webview都会重新加载

dart - 为什么未初始化Module.DEFAULT_REFLECTOR?

dart - 动态更改 AlertDialog 标题 (showDialog())

flutter - 在 Flutter 中创建自定义小部件

firebase - 用于 Flutter 的 Firestore 上的 Cloud Functions

dart - Flutter 从 Future<bool> 方法返回 bool 类型

flutter - 如何在 Dart 中查询列表列表?

mobile - Flutter Hero创建重复的文本

dart - 防止滚动的英雄跳到应用栏顶部

flutter - 自定义 Painter 类在 Stack Flutter 中不可见