Flutter 使用dart中的多个下拉列表筛选列表
嘿,谢谢你检查我的问题,我正在制作一个应用程序,它连接到一个api并像这样提取json数据 我一直在尝试让一个过滤系统工作,例如,列表可以按某个系列和其他选项排序,我在代码中有两个列表,一个用于api的所有结果,称为_userdetails,另一个用于搜索结果,称为_searchresult 我的目标是让过滤器和搜索栏同步工作,例如,您可以筛选一个名为“一件”的系列,然后使用其他过滤器筛选新列表,以缩小结果范围,甚至在这些新列表上使用搜索栏 目前,我有过滤器工作到一定程度,如果该系列被选为龙珠,它将选择所有的龙珠字符,但一旦一个新的过滤器或搜索被使用,它只是重置列表 这是下拉列表的代码Flutter 使用dart中的多个下拉列表筛选列表,flutter,dart,dropdown,Flutter,Dart,Dropdown,嘿,谢谢你检查我的问题,我正在制作一个应用程序,它连接到一个api并像这样提取json数据 我一直在尝试让一个过滤系统工作,例如,列表可以按某个系列和其他选项排序,我在代码中有两个列表,一个用于api的所有结果,称为_userdetails,另一个用于搜索结果,称为_searchresult 我的目标是让过滤器和搜索栏同步工作,例如,您可以筛选一个名为“一件”的系列,然后使用其他过滤器筛选新列表,以缩小结果范围,甚至在这些新列表上使用搜索栏 目前,我有过滤器工作到一定程度,如果该系列被选为龙珠
new Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// Text("Select a series"),
new DropdownButton<String>(
hint: Text("Series"),
// value: null,
items: _fieldList.map((value){
return DropdownMenuItem<String>(
value: value.series,
child: Container(
width: 100,
child: new Text(value.series),
// height: 5.0,
),
);
}).toList(),
onChanged: (String val) {
_selectedText = val;
setState(() {
// _searchResult.clear();
// _searchResult.removeWhere((userDetail) => userDetail.series != _selectedText);
// _newList.clear();
_selectedText = val;
_userDetails.forEach((userDetail) {
if(userDetail.series.contains(_selectedText)){
userDetail.remove((userDetail) => userDetail.series != _selectedText);
_searchResult.add(userDetail);}
if(_searchResult.contains(_selectedText))
_searchResult.removeWhere((userDetail) => userDetail.series != _selectedText);
// _userDetails.where((f) => f.series.contains(_selectedText)).toList(); //apples
print(_searchResult.length);
});
print(_selectedText);
});
},
),
new DropdownButton<String>(
hint: Text("Class"),
// value: null,
items: _fieldList.map((value){
return DropdownMenuItem<String>(
value: value.classs,
child: new Text(value.classs),
);
}).toList(),
onChanged: (String val) {
_selectedText = val;
setState(() {
_searchResult.removeWhere((userDetail) => userDetail.classs != _selectedText);
_userDetails.forEach((userDetail) {
if (userDetail.classs.contains(_selectedText))
///loops thrpugh each user detail and add where selectedtext = whatever
// _searchResult.removeWhere((_searchResult) => userDetail.classs != _selectedText);
_searchResult.removeWhere((userDetail) => userDetail.classs != _selectedText);
_searchResult.add(userDetail);
// _userDetails.where((f) => f.classs.contains(_selectedText)).toList(); //apples
/// _searchResult.add(userDetail);
});
// _searchResult.add(userDetail);
print(_selectedText);
//_searchResult.remove(userDetail.classs.)
//_newList.add(userDetail);
print(_searchResult.length);
// });
print(_selectedText);
});
},
),
SizedBox(
height: 5.0,
),
Text('Selected: ${_selectedText}'),
],
),
我有点困惑lol在搜索或更改过滤器后,您不断重置列表的原因是您正在调用setstate并分配值_selectedText=val。您正在为selectedText分配新值
//Excerpt from your code
onChanged: (String val) {
setState(() {
/// When the dropdown value changes you are assigning a new value to selected
/// text
/// Assuming it had Goto and the user selected Vegeta, the new value of
/// selectedText will be Vegeta
_selectedText = val;
// The statement that follows will evaluate based on the new value
});
});
我建议要么使用面向对象的方法,从这些字段创建模型,并使用I、e系列和类,要么使用映射而不是字符串。如果您觉得使用字符串更合适,请使用与过滤器数量相等的字符串。i.e将所选文本转换为映射。由于您使用的是下拉菜单,我的假设是,您只需要每个过滤器中的一个值
///Initialize your set outside the build method and results
final Map<String,String> selected = {"series":"","class":""}
/// Initialized the results list with the initial result set
List results = userDetails;
/// Method to build your results
void buildResults(){
setState((){
var seriesList =
/// comparing strings in dart is case sensitive so
/// depending on your data you may consider
/// converting all the strings you are comparing to lowercase
_userList
.where((userDetail)=>userDetail
.series
.toLowerCase()
.contains(selected["series"]))).toList();
var classList =
_userList
.where((userDetail)=>userDetail
.class.toLowerCase()
.contains(selected["class"]))).toList();
/// Merge the two lists using spread operator
/// Assuming you are using Dart > 2.3
var list3 = [...seriesList, ...classList];
results = list3;
});
}
/// onChanged method of Dropdown button
/// Assuming this is the series dropdown
setState((){
selected.update(
"series",
// if it is already in the map
(existingValue) => value,
ifAbsent: () => value,
);
buildResults();
});
/// In your listview builder
ListView.builder(
itemCount: results.length,
itemBuilder:(context,index){
}
///在生成方法和结果之外初始化集合
选择的最终映射={“系列”:““类”:”}
///使用初始结果集初始化结果列表
列表结果=用户详细信息;
///方法来生成结果
void buildResults(){
设置状态(){
变量系列列表=
///在dart中比较字符串区分大小写,因此
根据你的数据,你可以考虑
///将要比较的所有字符串转换为小写
_用户列表
.其中((userDetail)=>userDetail
系列
.toLowerCase()
.contains(选定的[“系列]))).toList();
变量类列表=
_用户列表
.其中((userDetail)=>userDetail
.class.toLowerCase()
.contains(选定的[“类]))).toList();
///使用扩展运算符合并两个列表
///假设您使用的Dart>2.3
var list3=[…系列列表,…类列表];
结果=列表3;
});
}
///下拉按钮的一次更改方法
///假设这是序列下拉列表
设置状态(){
已选择。更新(
“系列”,
//如果它已经在地图上了
(现有值)=>值,
ifAbsent:()=>值,
);
buildResults();
});
///在listview生成器中
ListView.builder(
itemCount:results.length,
itemBuilder:(上下文,索引){
}
你可以找到一个更有效的方法。你不需要调用setstate两次,我已经这样做了
///Initialize your set outside the build method and results
final Map<String,String> selected = {"series":"","class":""}
/// Initialized the results list with the initial result set
List results = userDetails;
/// Method to build your results
void buildResults(){
setState((){
var seriesList =
/// comparing strings in dart is case sensitive so
/// depending on your data you may consider
/// converting all the strings you are comparing to lowercase
_userList
.where((userDetail)=>userDetail
.series
.toLowerCase()
.contains(selected["series"]))).toList();
var classList =
_userList
.where((userDetail)=>userDetail
.class.toLowerCase()
.contains(selected["class"]))).toList();
/// Merge the two lists using spread operator
/// Assuming you are using Dart > 2.3
var list3 = [...seriesList, ...classList];
results = list3;
});
}
/// onChanged method of Dropdown button
/// Assuming this is the series dropdown
setState((){
selected.update(
"series",
// if it is already in the map
(existingValue) => value,
ifAbsent: () => value,
);
buildResults();
});
/// In your listview builder
ListView.builder(
itemCount: results.length,
itemBuilder:(context,index){
}