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 = [];
});
}