在Flutter中动态生成小部件

11
我试图根据特定条件动态生成一组小部件。在这种情况下,我正在尝试生成一组RadioTiles列表。
以下是我的生成方式:
  List _listings = new List();

  Widget _getListings() {
    // TODO this will accept json objects in order to display the data
    List listings = new List();
    int i = 0;
    for (i = 0; i < 5; i++) {
      listings.add(
        new RadioListTile<SingingCharacter>(
          title: const Text('Lafayette'),
          value: SingingCharacter.lafayette,
          groupValue: _character,
          onChanged: (SingingCharacter value) {
            setState(() {
              _character = value;
            });
          },
        ),
      );
    }
//     return listings;
  }

我正在尝试将其显示在类似于有状态的小部件中:

 return new SafeArea(
        child: Column(children: <Widget>[
      new Padding(
        padding: const EdgeInsets.all(20.0),
        child: new Text(
          "Verify and Select a Single Listing?",
          style: _textStyle,
        ),
      ),
      ListView(
        shrinkWrap: true,
        padding: const EdgeInsets.all(20.0),
        children: <Widget>[
          _getListings(),
        ],
      ),
    ]));

问题在于列表的值为空,因此我无法在屏幕上显示任何小部件。
任何见解都将很有用。
谢谢,
编辑:
如果我尝试返回一个列表,我看到的是: enter image description here 我不确定这是否是动态创建小部件的最佳方法。

1
你为什么注释掉了 return listings;?你为什么加上了 List _listings = new List();?看起来它没有被使用。 - Günter Zöchbauer
我将返回List<Widget>,并且我希望该列表在可滚动的小部件中显示,但是List<Widget>无法分配给小部件。我真的不确定这是否是创建动态数量的小部件的最佳方法。 - bhavs
“而且 List<Widget> 无法分配给 widget。”我不明白为什么这会在您的示例中引起问题。 - Günter Zöchbauer
3个回答

15

以下是您代码的一些更新:

      Widget build(BuildContext context) {

    return Scaffold(body: SafeArea(
        child: Container(child: Column(children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(20.0),
            child: Text("Verify and Select a Single Listing?",),
          ),
          Expanded(child:  ListView(
            padding: const EdgeInsets.all(20.0),
            children: _getListings(), // <<<<< Note this change for the return type
          ),
          )
        ])
        )));
  }

  List _listings = new List();

  List<Widget> _getListings() { // <<<<< Note this change for the return type
    List listings = List<Widget>();
    int i = 0;
    for (i = 0; i < 5; i++) {
      listings.add(
        RadioListTile<String>(
          title: const Text('Lafayette'),
          value: "c",
          groupValue: "x",
          onChanged: (_) {

          },
        ),
      );
    }
     return listings;
  }

以下是需要考虑的一些事项:

我做了一些更改,使代码能够编译并用于此答案。

  • 添加了对显著更改的注释
  • 列表_listings未使用
  • 在创建新对象时,您也可以省略new关键字(dart的新版本能够处理这个)

结果:

输入图像描述


如果StreamBuilder生成列表,则需要使用Widget _getListing()。我需要一个更通用的解决方案,使用像作者最初提出的那样的Widget。返回StreamBuilder<List<MyClass>>(...)。 - Golden Lion

1

这可以用来避免不必要的for循环。用两行代码实现同样的功能。

int numberOfWidgets = 5;
List<Widget> listings = List<Widget>.filled(numberOfWidgets, buildWidget());

这将创建一个精确数量的小部件列表。此方法仅在您希望在列表中使用类似类型的小部件时有用。

1

对之前回答的一些评论;

  • 请不要使用不必要的容器,如果一个容器只有一个子元素,那么请将其删除。
  • 不需要使用new关键字,在Dart linters中甚至建议不要使用。就像这里..

如果你的列表不会改变,你可以像下面的例子一样使用List.unmodifiable。

final List<Widget> widgets = List.unmodifiable(() sync* {
  for (int i = 0; i < 5; i++) {
    yield RadioListTile<String>(
      title: const Text('Lafayette'),
      value: "c",
      groupValue: "x",
      onChanged: (_) {

      },
    );
  }
}());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接