Flutter/Dart:处理ListView.builder中的Dropdown更改,Dropdown按钮不更新



我猜我错过了一些简单的东西,但我已经尝试了好几天所有可能的解决方案。我们如何处理listview.builder中的下拉选择?是否可以将下拉按钮值存储在列表字符串中?

我正在创建一个基于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];
},
));
}
}

我最终用statefulbuilder包装了每个下拉小部件(在List<Widget>中(,所以当从每个小部件调用setstate时,只有该小部件会更新,但如果需要,仍然可以使用整个树。通过这种方式,根据anmol.majhail注释从构建中调用setState。

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"));
}
}

以下代码运行良好。因为CCD_ 2再次调用Build方法&再次绘制CCD_ 3。在您的代码中,CCD_ 4被放置在_;此值在整个代码周期中保持静态。即使在调用SetState之后,它也将保持不变——因为SetState不会更新_widgets[0]值——它只会再次调用Build Method。

@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并动态更新List,然后设置State。

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

然后根据触发器/事件对其进行更新。

_buildDropDownList() {
if (dropDownEnabled) {
setState (() {
dropDownList.addAll([1,2,,4,5])
});
} else {
setState (() {
dropDownList = [];
});   
}

最新更新