Динамически генерировать виджеты в Flutter

#flutter

#flutter

Вопрос:

Я пытаюсь динамически генерировать набор виджетов на основе определенного условия. В этом случае я пытаюсь сгенерировать список радиосигналов

Вот как я пытаюсь сгенерировать

   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(),
        ],
      ),
    ]));
  

Проблема в том, что значение listings равно null, из-за чего я не могу отобразить какие-либо виджеты на экране.

Любая информация была бы полезна.

Спасибо,

Редактировать :

Если я попытаюсь вернуть список, это то, что я вижу: введите описание изображения здесь

Я не уверен, что это лучший способ динамического создания виджетов.

Комментарии:

1. Почему вы закомментировали return listings; ? Почему вы добавили List _listings = new List(); ? Не похоже, что это используется.

2. Тогда я бы вернул список<Widget>, и я хочу, чтобы список отображался в виджете с возможностью прокрутки, а список<Widget> не может быть назначен виджету. Я действительно не уверен, что это лучший способ создать динамическое количество виджетов.

3. «и список<Widget> не может быть назначен виджету». Я не понимаю, почему это может вызвать проблемы в вашем примере.

Ответ №1:

Вот некоторые обновления для вашего кода:

       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 способна справиться с этим)

Результат:

введите описание изображения здесь

Комментарии:

1. Виджет _getListing() необходимо использовать, если streambuilder генерирует список. Мне нужно более универсальное решение с использованием виджета, подобного первоначально предложенному автором. вернуть StreamBuilder<Список<MyClass>>(…)

Ответ №2:

Некоторые комментарии к предыдущему ответу;

  • Пожалуйста, не используйте ненужные контейнеры, если в контейнере есть только дочерний элемент и ничего больше, удалите его.
  • Ключевое слово 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: (_) {

      },
    );
  }
}());
  

Ответ №3:

Это можно использовать, чтобы избежать ненужных for loop . Делаем то же самое в 2 строках

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

Это позволит составить список с точным количеством виджетов.
Кроме того, это полезно только в том случае, если вам нужен виджет аналогичного типа в списке