如何在Flutter中实现可搜索、支持多选并存储选中项的ListView
Flutter可搜索ListView多选功能实现方案
实现思路
你需要在现有代码基础上做3处核心改动即可满足需求:
- 新增状态变量存储选中的科目列表
- 为列表条目增加选中状态交互、点击多选逻辑
- 新增选中条目展示区域,支持直接取消选中
完整修改后代码
import 'package:flutter/material.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; // 你原有代码中已定义的科目列表,这里做示例,可根据实际情况调整 const List<String> subjectList = [ '语文', '数学', '英语', '物理', '化学', '生物', '政治', '历史', '地理' ]; class MainScreen extends StatefulWidget { const MainScreen({Key? key}) : super(key: key); @override _MainScreenState createState() => _MainScreenState(); } class _MainScreenState extends State<MainScreen> { TextEditingController _textEditingController = TextEditingController(); var showError = false; List<String> subjectListOnSearch = []; // 新增:存储选中的科目列表 List<String> selectedSubjects = []; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Select Subject'), // 新增:右上角展示选中数量,点击可做提交等后续操作 actions: [ Padding( padding: const EdgeInsets.only(right: 16), child: Center(child: Text('已选: ${selectedSubjects.length}')), ) ], bottom: PreferredSize( preferredSize: const Size.fromHeight(45), child: Container( margin: const EdgeInsets.only(left: 10, right: 10, bottom: 7), child: TextField( onChanged: (value) { setState(() { subjectListOnSearch = subjectList .where((element) => element .toLowerCase() .contains(value.toLowerCase())) .toList(); showError = value.trim().isNotEmpty; }); }, controller: _textEditingController, decoration: InputDecoration( suffixIcon: Visibility( visible: showError, child: IconButton( icon: const Icon(Icons.close, color: Colors.blue), onPressed: () { subjectListOnSearch.clear(); _textEditingController.clear(); setState(() { showError = false; }); }), ), hintText: 'Search Subject', prefixIcon: const Icon(Icons.search), border: InputBorder.none, errorBorder: InputBorder.none, focusedBorder: InputBorder.none, ), ), ), ), ), // 改为Column布局,顶部放选中项展示区,下方放列表 body: Column( children: [ // 新增:选中条目展示区 if(selectedSubjects.isNotEmpty) Padding( padding: const EdgeInsets.all(10), child: Wrap( spacing: 8, runSpacing: 6, children: selectedSubjects.map((subject) { return Chip( label: Text(subject), deleteIcon: const Icon(Icons.close, size: 16), onDeleted: () { setState(() { selectedSubjects.remove(subject); }); }, ); }).toList(), ), ), // 原有列表逻辑 Expanded( child: _textEditingController.text.isNotEmpty && subjectListOnSearch.isEmpty ? const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.search_off, color: Colors.red, size: 100, ), Text('No Results Found'), ], ), ) : ListView.builder( itemCount: _textEditingController.text.isNotEmpty ? subjectListOnSearch.length : subjectList.length, itemBuilder: (BuildContext context, index) { final currentSubject = _textEditingController.text.isNotEmpty ? subjectListOnSearch[index] : subjectList[index]; final isSelected = selectedSubjects.contains(currentSubject); return Padding( padding: const EdgeInsets.only(left: 15, top: 15), // 新增:ListTile增加选中状态、点击事件、选中标识 child: ListTile( selected: isSelected, selectedTileColor: Colors.blueAccent.withOpacity(0.1), onTap: () { setState(() { if(isSelected){ selectedSubjects.remove(currentSubject); }else{ selectedSubjects.add(currentSubject); } }); }, leading: CircleAvatar( radius: 25, backgroundColor: Colors.blueAccent, child: Icon(MdiIcons.bookOpenPageVariant), ), title: Text(currentSubject), trailing: isSelected ? const Icon(Icons.check_circle, color: Colors.green) : null, ), ); }), ), ], ), ); } }
功能说明
- 多选交互:点击列表条目即可切换选中状态,选中的条目会高亮底色、右侧显示勾选标识
- 选中存储:所有选中的科目自动存入
selectedSubjects列表,可直接读取该列表做后续提交等操作 - 选中展示:页面顶部会用标签形式展示所有选中的科目,点击标签右侧的删除按钮可直接取消选中,AppBar右上角实时显示已选数量
内容的提问来源于stack exchange,提问作者Kashif Hafeez
相关产品推荐
相关产品推荐

