flutter - 在 dart 中过滤具有多个下拉列表的列表
问题描述
嘿,感谢您查看我的问题,我正在制作一个连接到 api 并像这样拉回 json 数据的应用程序
我一直在尝试让过滤系统工作,例如列表可以按某个系列和其他选项排序,我在代码中有两个列表,一个用于来自名为 _userdetails 的 api 的所有结果,另一个用于搜索结果称为_searchresult。
我的目标是让过滤器和搜索栏同步工作,例如,您可以过滤一个名为 one piece 的系列,然后使用其他过滤器过滤该新列表以缩小结果范围,甚至在这些新的列表。
目前我的过滤器在一定程度上工作,如果该系列被选为龙珠,它将选择所有的龙珠字符,但是一旦使用新的过滤器或搜索,它只会重置列表这里是下拉列表的代码
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}'),
],
),
这是列表视图的代码
new Expanded(
child: _searchResult.length != 0 || controller.text.isNotEmpty
? new ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (context, i) {
return new Card(
child: new ListTile(
leading: new CircleAvatar(backgroundImage: new NetworkImage("https://ochd.co.uk/db/puti/Assets/Portraits/"+_searchResult[i].portrait,),),
title: new Text(_searchResult[i].name),
subtitle: new Text(_searchResult[i].classs),
onTap: () {
Navigator.push(context, new MaterialPageRoute(builder: (context) => DetailPage(_searchResult[i])));},
),
margin:
const EdgeInsets.all(0.0),
);
},
)
: new ListView.builder(
itemCount: _userDetails.length,
itemBuilder: (context, index) {
return new Card(
child: new ListTile(
leading: new CircleAvatar(backgroundImage: new NetworkImage("https://ochd.co.uk/db/puti/Assets/Portraits/"+_userDetails[index].portrait,),),
title: new Text(_userDetails[index].name),
subtitle: new Text(_userDetails[index].classs),
trailing: new CircleAvatar(backgroundImage: new NetworkImage("https://ochd.co.uk/db/puti/Assets/"+_userDetails[index].type,),),
onTap: () {
Navigator.push(context, new MaterialPageRoute(builder: (context) => DetailPage(_userDetails[index])));},
),
margin: const EdgeInsets.all(0.0),
);
},
),
),
我有点难过哈哈
解决方案
您在搜索或更改过滤器后继续重置列表的原因是您正在调用 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 系列和类或使用映射而不是字符串。如果您发现字符串更舒服,则使用与过滤器数量相等的字符串,即将 selectedText 转换为 Map。由于您使用的是 DropdownMenu 我的假设是您只需要每个过滤器中的一个值
///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){
}
你可以找到更有效的方法。你不需要调用 setstate 我已经完成了两次。
推荐阅读
- sqlite - SQLITE 查询 AVG 子选择/加入
- html - 隐藏 CSS 动画的内容溢出
- javascript - 无法执行 .map whithin 功能
- php - 如何使路由上使用的中间件可以在 Laravel 的测试中工作
- ios - Firebase App Distribution 不显示我所有可用的 IOS 应用程序
- spring - 如何使我的第二个下拉列表依赖于 Springboot Thymeleaf 中的第一个下拉列表?
- postgresql - 更新 Postgres 目标中选定记录的问题 - Talend 7X Open studio
- java - MyBatis mapper 界面在 List of Maps 中保留列顺序
- node.js - 在heroku部署期间如何从删除文件夹中排除?
- xcode - 如何在 Xcode 中使用 Testflight 构建?