Flutter/Dart: обработка выпадающих изменений в ListView.builder, кнопка Dropdown не обновляется,

Я предполагаю, что упускаю что-то простое, но я занимался этим несколько дней, пытаясь найти любое возможное решение. Как мы управляем выпадающим списком в listview.builder? Можно ли сохранить значения выпадающих кнопок в List-String-?

Я создаю динамическую форму, основанную на шаблонах XML и имеющую выпадающие списки, флажки, ввод и т. Д. РЕДАКТИРОВАТЬ: я не знаю, какие виджеты требуются, пока XML не будет проанализирован при загрузке страницы. Отсюда попытка передать динамически созданный список виджетов в Listview.builder.

Код ниже - это основной пример, который не удалось обновить.

Цените любые советы здесь.

import 'package:flutter/material.dart';

class FormEG extends StatefulWidget {
  @override
  _FormEGState createState() => new _FormEGState();
}

class _FormEGState extends State<FormEG> {
  List<String> _listValues;
  List<DropdownMenuItem<String>> _items;
  List<Widget> _widgets;

  @override
  void initState() {
    _listValues = new List<String>();
    _listValues.add("b");

    _items = new List<DropdownMenuItem<String>>();
    _items.add(new DropdownMenuItem(child: Text("a"), value: "a"));
    _items.add(new DropdownMenuItem(child: Text("b"), value: "b"));
    _items.add(new DropdownMenuItem(child: Text("c"), value: "c"));
    _items.add(new DropdownMenuItem(child: Text("d"), value: "d"));

    _widgets = new List<Widget>();
    _widgets.add(new DropdownButton<String>(
      value: _listValues[0],
      items: _items,
      onChanged: (String newValue) {
        setState(() {
          _listValues[0] = newValue;
        });
      },
    ));
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: new ListView.builder(
          itemCount: _widgets.length,
          itemBuilder: (context, index) {
          return _widgets[index];
          },
        ));
      }
  }

2 ответа

Я закончил оборачивать каждый выпадающий виджет (в List<Widget>) с помощью Stateful Builder, чтобы при вызове setstate из каждого виджета обновлялся только этот виджет, но при необходимости можно обновлять все дерево. Таким образом, setState вызывается из сборки согласно комментариям anmol.majhail.

import 'package:flutter/material.dart';

class FormEG extends StatefulWidget {
  @override
  _FormEGState createState() => new _FormEGState();
}

class _FormEGState extends State<FormEG> {
  List<String> _listValues;
  List<DropdownMenuItem<String>> _items;
  List<Widget> _widgets;

  @override
  void initState() {
    _listValues = new List<String>();
    setDefaults();
    setWidgets();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    print("built");
    return new Scaffold(
        body: new ListView.builder(
          itemCount: _widgets.length,
          itemBuilder: (context, index) {
        return _widgets[index];
      },
    ));
  }

  void setDefaults() {
    _listValues.add("b");
  }

  void setWidgets() {
    setMenuItems();
    _widgets = new List<Widget>();
    _widgets.add(
      new StatefulBuilder(
        builder: (BuildContext context, StateSetter setState) {
          return new DropdownButton<String>(
            value: _listValues[0],
            items: _items,
            onChanged: (String newValue) {
              setState(() {
                _listValues[0] = newValue;
              });
            },
          );
        },
      ),
    );
  }

  void setMenuItems() {
    _items = new List<DropdownMenuItem<String>>();
    _items.add(new DropdownMenuItem(child: Text("a"), value: "a"));
    _items.add(new DropdownMenuItem(child: Text("b"), value: "b"));
    _items.add(new DropdownMenuItem(child: Text("c"), value: "c"));
    _items.add(new DropdownMenuItem(child: Text("d"), value: "d"));
  }
}

Следующий код работает хорошо. Так как SetSate Снова вызывает метод Build & DropdownButton Рисуется снова. В вашем коде DropdownButton помещается в значение _widgets[0], и это значение остается статическим в цикле кода. Даже после звонка SetState оно останется таким же - потому что SetState не будет обновлять значение _widgets[0] - снова будет вызываться только метод сборки.

@override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: new ListView.builder(
      itemCount: _widgets.length,
      itemBuilder: (context, index) {
        return DropdownButton<String>(
          value: _listValues[0],
          items: _items,
          onChanged: (newValue) {
            setState(() {
              _listValues[0] = newValue;
            });
          },
        );
      },
    ));
  }

Вы можете попробовать просто использовать List и динамически обновлять список, а затем setState.

ListView(
                  shrinkWrap: true,
                  scrollDirection: Axis.vertical,
                  children: dropDownList),
            ),

Затем обновите его на основе триггера / события.

 _buildDropDownList() {
     if (dropDownEnabled) {
       setState (() {
         dropDownList.addAll([1,2,,4,5])
       });
       } else {
        setState (() {
         dropDownList = [];
      });   
    }
Другие вопросы по тегам