我有过滤我的列表的搜索字段,它工作正常,我只想对其进行一些小的更改:
逻辑
ListTile->subtitle
中,目前只搜索title
代码 search function is commented for better understanding
List<World> locations = [...]
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
buildSearch(),
Expanded(
child: ListView.builder(
itemCount: locations.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
onTap: () {},
title: Text(locations[index].location),
subtitle: Text(locations[index].country),
),
),
},
),
),
],
),
),
}
Widget buildSearch() => SearchWidget(
text: query,
hintText: 'Search for location',
onChanged: searchLocation,
);
void searchLocation(String query) async {
// currently only search in titles (need to add subtitle as well)
final newLocations = locations.where((location) {
final nameLower = location.location.toLowerCase();
final searchLower = query.toLowerCase();
return nameLower.contains(searchLower);
}).toList();
// when user clear search or remove letters list wont back to it's default
setState(() {
this.query = query;
this.locations = newLocations;
});
}
有什么建议吗?
这是我的 SearchWidget
文件(以防万一)
class SearchWidget extends StatefulWidget {
final String text;
final ValueChanged<String> onChanged;
final String hintText;
const SearchWidget({
Key key,
this.text,
this.onChanged,
this.hintText,
}) : super(key: key);
@override
_SearchWidgetState createState() => _SearchWidgetState();
}
class _SearchWidgetState extends State<SearchWidget> {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
final styleActive = TextStyle(color: Colors.black);
final styleHint = TextStyle(color: Colors.black54);
final style = widget.text.isEmpty ? styleHint : styleActive;
return Container(
height: 42,
margin: const EdgeInsets.fromLTRB(16, 16, 16, 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
border: Border.all(color: Colors.black26),
),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: TextField(
controller: controller,
decoration: InputDecoration(
icon: Icon(Icons.search, color: style.color),
suffixIcon: widget.text.isNotEmpty
? GestureDetector(
child: Icon(Icons.close, color: style.color),
onTap: () {
controller.clear();
widget.onChanged('');
FocusScope.of(context).requestFocus(FocusNode());
},
)
: null,
hintText: widget.hintText,
hintStyle: style,
border: InputBorder.none,
),
style: style,
onChanged: widget.onChanged,
),
);
}
}
我已经设法在我的逻辑中修复了 #2 并通过以下代码获得了包含搜索结果的字幕(清晰的搜索问题仍然存在)
void searchLocation(String query) async {
final newLocations = locations.where((location) {
final nameLower = location.location.toLowerCase();
final countryLower = location.country.toLowerCase(); // added
final searchLower = query.toLowerCase();
return nameLower.contains(searchLower) || countryLower.contains(searchLower); //changed
}).toList();
setState(() {
this.query = query;
this.locations = newLocations;
});
}
注意:
我已接受 Yair Chen
答案,但我需要澄清一些问题以解决此问题:
根据 Yair Chen
答案,我必须创建新列表 List<World> filteredLocations = [];
然后在我的 ListView.builder
中,我更改了 itemCount
和 child
,如下所示:
ListView.builder(
itemCount: filteredLocations.isNotEmpty ? filteredLocations.length : locations.length,
//...
child: filteredLocations.isNotEmpty ? card(... //filteredLocations[index].location//...) : Card(... //locations[index].location// ...),
通过这种方式解决了过滤结果的索引问题,卡片数据将获取有关它们返回的列表的数据。
答案 0 :(得分:0)
您可以添加另一个名为 filtersLocations 的列表,然后将新列表保存到过滤位置。函数 .where() 也会更改您不想要的原始列表。您可以浅复制(使用扩展运算符)列表,然后创建一个与查询匹配的新列表,如下所示:
void searchLocation(String query) async {
// currently only search in titles (need to add subtitle as well)
// [...locations] copies the list to not change original list
final newLocations = [...locations].where((location) {
final nameLower = location.location.toLowerCase();
final searchLower = query.toLowerCase();
// Also adding subtitle check (whether the name contains it or the subtitle does
return nameLower.contains(searchLower) || location.subtitle.toLowerCase().contains(searchLower);
}).toList();
// when user clear search or remove letters list wont back to it's default
setState(() {
this.query = query;
this.filteredLocations = newLocations;
});
}
这样原始列表永远不会改变,只有filteredList会被更新。它还将解决当字符串为空时您希望所有项目都出现的问题。
祝您好运,如果您需要其他任何东西,请告诉我:)