自定义主题无法正常工作. [扑] [英] Custom theme not working properly. [Flutter]

查看:82
本文介绍了自定义主题无法正常工作. [扑]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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]时,它默认为蓝色.另外,尝试使用自定义字体Sunflower字体系列不起作用,但是当我改用

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

字体正确显示.

我是扑扑和飞镖的新手,所以解决这些问题的任何帮助将不胜感激.

解决方案

这与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()等),查看传递它们的上下文,然后向上遍历小部件树,以查找指定类型的小部件. /p>

现在,查看您的代码

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

您可以看到,传递给Theme.ofcontext实际上是所创建主题上方的上下文.因此,它将找不到您的主题,并将恢复为默认主题.这是因为窗口小部件树看起来类似于以下内容(忽略所有中间层,箭头指向您正在使用的上下文.

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对.

I have created the following theme for my app:

ThemeData _buildDarkTheme() {
  final baseTheme = ThemeData(fontFamily: "Sunflower",);
  return baseTheme.copyWith(
      brightness: Brightness.dark,
      primaryColor: Colors.grey[800],
      accentColor: Colors.grey[850]);
}

I then apply it to my app as follows:

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(...

However, when I try to access the accent color inside the container (or anywhere else) instead of it being the expected, Colors.grey[850], it instead defaults to blue. Also, trying to use the custom font Sunflower font family does not work, but when I instead use

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

The font appears correctly.

I am new to flutter and dart so any help resolving these issues would be appreciated.

解决方案

This is to do with how context and Theme.of work.

From the Theme class source code:

  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 (and Navigator.of(), ....of() etc), look at the context you pass them and then iterate upwards through the tree of widgets looking for a widget of the type specified.

Now, looking at your code

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

you can see that the context you're passing into Theme.of is actually the context above the theme you're creating. So it won't find your theme and will revert to the default. This is because the widget tree looks somewhat like the following (ignoring all the intermediate layers, with the arrow pointing to the context you're using.

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

There are two ways to fix this; the first is to use a Builder class to build your widget within a closure that has the context below the theme. That would look something like this:

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(...
    ))

And it would make a tree that looks somewhat like this:

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

The other (preferable) option is to split out the code for your builder into its own class - either a StatelessWidget-inherited class or a StatefulWidget and State pair.

这篇关于自定义主题无法正常工作. [扑]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆