如何有条件地将小部件添加到列表中?

Posted

技术标签:

【中文标题】如何有条件地将小部件添加到列表中?【英文标题】:How to conditionally add widgets to a list? 【发布时间】:2019-02-03 06:21:15 【问题描述】:

在 Flutter 中,Row/ListView/Stack 等小部件不处理 null 子级。因此,如果我们想有条件地将小部件添加为子小部件,我通常会执行以下操作:

Row(
  children: <Widget>[
    foo == 42 ? Text("foo") : Container(),
  ],
);

但是添加一个空容器感觉很奇怪。

另一种解决方案是where 过滤器:

Row(
  children: <Widget>[
    foo == 42 ? Text("foo") : null,
  ].where((t) => t != null).toList(),
);

这样解决了空容器的问题,但是我们仍然有一个丑陋的三元,写起来很累。

有没有更好的解决方案?

【问题讨论】:

【参考方案1】:

编辑

从 Dart 2.2 开始,新语法原生支持这一点:

Column(
  children: [
    if (foo != null) Text(foo),
    Bar(),
  ],
);

这个问题目前在github上讨论here。

但现在,你可以使用 dart sync* 函数:

Row(
  children: toList(() sync* 
    if (foo == 42) 
      yield Text("foo");
    
  ),
);

toList 在哪里:

typedef Iterable<T> IterableCallback<T>();

List<T> toList<T>(IterableCallback<T> cb) 
  return List.unmodifiable(cb());


不仅解决了条件加法问题;由于yield*,它还允许“传播运算符”。示例:

List<Widget> foo;

Row(
  children: toList(() sync* 
    yield Text("Hello World");
    yield* foo;
  ),
);

【讨论】:

太棒了! List.of(_buildChildren()) 怎么样,_buildChildrensync* 方法? 也可以。但是当你想传递参数时使用它有点无聊。关闭使它更容易【参考方案2】:

新的 Dart 语法允许在列表中使用 'if',这导致了这个简单的解决方案:

Row(
  children: <Widget>[
    if (foo == 42) Text("foo"),
  ],
);

【讨论】:

【参考方案3】:

这是我使用的更简单的版本:

Row(
  children: [
    Text("always included"),
    skipNulls([
      icon,
      label,
    ]),
  ],
);

skipNulls<T>(List<T> items) 
  return items..removeWhere((item) => item == null);

【讨论】:

【参考方案4】:

Row(
    children: [
        if (_id == 0) ...[
          Container()
        ] else if(_id == 1)...[
          Text("Hello")
        ] else ...[
          SizedBox(width: 20)
        ],
    ],
 ),

【讨论】:

以上是关于如何有条件地将小部件添加到列表中?的主要内容,如果未能解决你的问题,请参考以下文章

在颤动中动态地将小部件添加到列的子项

如何将小部件添加到 Dojo gridx/Grid 标题?

如何将小部件动态添加到网格?

更改通知提供程序以将小部件添加到收藏屏幕

netbeans:如何将小部件添加到 QT 变量

如何从我的应用程序将小部件添加到 Android 主屏幕?