自定义ListTile继承主题

时间:2019-10-21 01:00:05

标签: flutter

我需要继承自定义ListTile上的主题。

我创建了一个没有继承自定义列表的自定义ListTile,只是一个全状态的小部件。如何使它继承ListTile的所有主题?

通常,我通常会在单个窗口小部件上实现这一目标,并将特定值设置为Theme.of(context).whateverTheme.whateverValue。到目前为止,它一直没有任何问题,但是现在我看到即使list_tile.dart拥有.ListViewTheme.ListTileTheme也没有使用。它可能没有暴露。

这使我怀疑自己这是否是正确的方法。

在代码中查找<= I want here

class CustomMenuTile extends StatefulWidget {
  CustomMenuTile({Key key, this.selected, this.icon, this.text, this.routePage})
      : super(key: key);

  final bool selected;
  final IconData icon;
  final String text;
  final Widget routePage;

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

class _CustomMenuTileState extends State<CustomMenuTile> {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      constraints: BoxConstraints.expand(height: 48),
      child: Material(
        color: widget.selected ? kPrimarySwatch[400].withAlpha(100) : null,
        borderRadius: BorderRadius.all(Radius.circular(4)),
        child: InkWell(
            splashColor: Colors.grey.withAlpha(64),
            highlightColor: Colors.grey.withAlpha(64),
            borderRadius: BorderRadius.all(Radius.circular(4)),
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 12.0),
              child: Row(
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Padding(
                      padding: const EdgeInsets.only(right: 24),
                      child: Icon(widget.icon,
                        color: widget.selected
                            ? Theme.of(context).accentColor
                            : null, <= I want here Theme.of(context).ListViewTheme.iconColor
                      )),
                  Text(widget.text,
                      style: TextStyle(
                          fontWeight: FontWeight.bold,
                          color: widget.selected
                              ? Theme.of(context).accentColor
                              : null)),
                ],
              ),
            ),
            onTap: () {
              Navigator.pop(context);
              Navigator.of(context)
                  .pushReplacement(_createFadeRoute(widget.routePage));
            }),
      ),
    );
  }
}

3 个答案:

答案 0 :(得分:1)

您可以使用ListTileTheme.of(context).textColorListTileTheme的任何属性。

如果应用未定义ListTileTheme,则所有属性均返回null。在这种情况下,ListTile定义它自己的值。您可以查看默认值ListTile并使用,如果ListTileTheme的属性为null

答案 1 :(得分:0)

我认为null确实使用默认值。您可能正在寻找textTheme属性。

                Text(widget.text,
                  style: TextStyle(
                      fontWeight: FontWeight.bold,
                      color: widget.selected
                          ? Theme.of(context).accentColor
                          : Theme.of(context).textTheme.body.color),

答案 2 :(得分:0)

在list_tile.dart内部查看似乎该颜色正在从ListTileTheme中获取颜色,但是一旦您不将代码包装在ListTileTheme小部件中,该应用程序就会表现为它实际上没有该代码是真的。

在这种情况下,它只适用于硬编码的颜色Colors.black45,但这仅适用于ListTile的图标,而不是常规的Icon小部件。

Color _iconColor(ThemeData theme, ListTileTheme tileTheme) {
    if (!enabled)
      return theme.disabledColor;

    if (selected && tileTheme?.selectedColor != null)
      return tileTheme.selectedColor;

    if (!selected && tileTheme?.iconColor != null)
      return tileTheme.iconColor;

    switch (theme.brightness) {
      case Brightness.light:
        return selected ? theme.primaryColor : Colors.black45;
      case Brightness.dark:
        return selected ? theme.accentColor : null; // null - use current icon theme color
    }
    assert(theme.brightness != null);
    return null;
}

在github上有一个关于ThemeData上缺少的TileListTheme的公开问题。 https://github.com/flutter/flutter/issues/31247


以下是解决方法的完整示例:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListTileTheme(
      iconColor: Colors.blue,
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("ListTileTheme example"),
      ),
      body: ListView(
        children: <Widget>[
          ListTile(
            title: Text("ListTile IS inheriting the color"),
            leading: Icon(Icons.list),
          ),
          Row(
            children: <Widget>[
              Icon(Icons.list),
              Text("Other Icon is NOT inheriting the color..."),
            ],
          ),
          Row(
            children: <Widget>[
              Icon(Icons.list, color: ListTileTheme.of(context).iconColor),
              Text("...unless you use ListTileTheme.of(context).iconColor"),
            ],
          ),
        ],
      ),
    );
  }
}

此代码将产生以下结果:

Workaround example