自定义主题无法正常工作。 [扑]

时间:2018-06-18 20:56:54

标签: dart flutter

我为我的应用创建了以下主题:

ThemeData _buildDarkTheme() {
  final baseTheme = ThemeData(fontFamily: "Sunflower",);
  return baseTheme.copyWith(
      brightness: Brightness.dark,
      primaryColor: Colors.grey[800],
      accentColor: Colors.grey[850]);
}
然后我按照以下方式将它应用到我的应用程序:

class MyApp extends StatelessWidget {
  MyApp({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        theme: _buildDarkTheme(),
        home: new Scaffold(
          appBar: _buildAppBar(),
          body: new Container(
            color: Theme.of(context).accentColor,
            height: double.infinity,
            child: new ListView.builder(...

但是,当我尝试访问容器内部(或其他任何地方)的重点颜色而不是预期的Colors.grey [850]时,它默认为蓝色。此外,尝试使用自定义字体向日葵字体系列不起作用,但当我改为使用

new Text("Hello World", style: new TextStyle(fontFamily: "Sunflower"))

字体显示正确。

我是新手,因为任何解决这些问题的帮助都会受到欢迎。

3 个答案:

答案 0 :(得分:7)

这与contextTheme.of的工作方式有关。

来自Theme类源代码:

  static ThemeData of(BuildContext context, { bool shadowThemeOnly = false }) {
    final _InheritedTheme inheritedTheme =
        context.inheritFromWidgetOfExactType(_InheritedTheme);
    if (shadowThemeOnly) {
      if (inheritedTheme == null || inheritedTheme.theme.isMaterialAppTheme)
        return null;
      return inheritedTheme.theme.data;
    }

    final ThemeData colorTheme = (inheritedTheme != null) ? inheritedTheme.theme.data : _kFallbackTheme;
    final MaterialLocalizations localizations = MaterialLocalizations.of(context);
    final TextTheme geometryTheme = localizations?.localTextGeometry ?? MaterialTextGeometry.englishLike;
    return ThemeData.localize(colorTheme, geometryTheme);
  }

Theme.of(和Navigator.of(),...。of()等),查看传递它们的上下文,然后向上遍历窗口小部件树,寻找窗口小部件指定的类型。

现在,看看你的代码

Widget build(BuildContext context) {
    return new MaterialApp(
        theme: _buildDarkTheme(),
        home: new Scaffold(
          appBar: _buildAppBar(),
          body: new Container(
            color: Theme.of(context).accentColor,

您可以看到,context传入Theme.of的{​​{1}}实际上是您正在创建的主题之上的上下文。因此它无法找到您的主题并将恢复为默认值。这是因为窗口小部件树看起来有点像下图(忽略所有中间层,箭头指向您正在使用的上下文。

MyApp - context <--------
  MaterialApp
    Theme
      Scaffold

有两种方法可以解决这个问题;第一种是使用Builder类在具有主题下方的上下文的闭包内构建窗口小部件。这看起来像这样:

class MyApp extends StatelessWidget {
  MyApp({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        theme: _buildDarkTheme(),
    home: new Scaffold(
    appBar: _buildAppBar(),
    body: new Builder(builder: (context) => new Container(
      color: Theme.of(context).accentColor,
      height: double.infinity,
      child: new ListView.builder(...
    ))

它会使树看起来像这样:

MyApp - context
  MaterialApp
    Theme
      Scaffold
        Builder - context <---------

另一个(首选)选项是将构建器的代码拆分为自己的类 - StatelessWidget - 继承的类或StatefulWidgetState对。

答案 1 :(得分:1)

为什么不这样创建_darkTheme变量:

ThemeData _darkTheme = new _buildDarkTheme();

然后用它来定义颜色?

class MyApp extends StatelessWidget {
  MyApp({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        theme: _buildDarkTheme(),
        home: new Scaffold(
          appBar: _buildAppBar(),
          body: new Container(
            color: _darkTheme.accentColor,
            height: double.infinity,
            child: new ListView.builder(...

答案 2 :(得分:1)

在MaterialApp类中使用主题时,我遇到了同样的问题。如果您只希望整个Flutter应用程序具有一个主题,则只需在主页中使用一个主题(调用所有其他页面的主题)即可。

这样做之后,在其他页面中,请不要返回MaterialApp类,否则它将覆盖您的主题并使用默认主题。

这是我主页的代码:

            Widget build(BuildContext context) {

            return MaterialApp(
            theme: ThemeData(
            fontFamily: "Test",
            primaryColor: Colors.yellow,
            buttonColor: Colors.yellow,
             ),
             routes: {

             '/': (BuildContext context) => AuthPage(),
                },
             );

然后,在AuthPage中,返回Scaffold而不是MaterialApp。