Flutter/Dart: Handling Dropdown changes within a ListView.builder, Dropdown button not updating,
I ended up wrapping each dropdown widget (in List<Widget>
) with a statefulbuilder so when setstate is called from each widget only that widget is updated but one can still udate the entire tree if needed. In this way setState is called from within a build as per anmol.majhail comments.
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")); }}
Following Code Works Well. Because SetSate
Calls the Build method Again & DropdownButton
is Drawn again. In your Code DropdownButton
is placed at _widgets[0] value & this Value Stays Static through the code cycle. Even after Calling SetState
it will remain same - because SetState
wont update _widgets[0] value - it will only call Build Method Again.
@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; }); }, ); }, )); }
You could try just using a List and update the List dynamically and then setState.
ListView( shrinkWrap: true, scrollDirection: Axis.vertical, children: dropDownList), ),
Then update it based on a trigger/event.
_buildDropDownList() { if (dropDownEnabled) { setState (() { dropDownList.addAll([1,2,,4,5]) }); } else { setState (() { dropDownList = []; }); }