Flutter中为SQLite数据列表添加搜索框的实现求助
Flutter SQLite列表添加搜索功能实现方案
核心思路(新手友好)
- 用
TextEditingController监听搜索输入,实时获取关键词 - 维护两个列表:一个存数据库拉取的全部原始数据,一个存过滤后的结果,避免频繁查询数据库
- 输入变化时触发过滤逻辑,调用
setState更新UI
完整修改代码
首先在你的State类里添加这些变量:
// 存储从数据库获取的所有原始数据 List<Map<String, dynamic>> _allJournals = []; // 存储过滤后要展示的数据 List<Map<String, dynamic>> _filteredJournals = []; // 搜索输入控制器 final _searchController = TextEditingController();
然后修改数据刷新方法(比如你原来的_refreshJournals),把数据同时赋值给两个列表:
void _refreshJournals() async { final data = await SQLHelper.getItems(); setState(() { _allJournals = data; _filteredJournals = data; // 初始状态显示全部数据 _isLoading = false; }); }
添加搜索过滤逻辑:
void _filterJournals(String query) { List<Map<String, dynamic>> results = []; if (query.isEmpty) { // 搜索框为空时,显示全部数据 results = _allJournals; } else { // 按标题、描述模糊匹配,忽略大小写 results = _allJournals.where((journal) => journal['title'].toLowerCase().contains(query.toLowerCase()) || journal['description'].toLowerCase().contains(query.toLowerCase())).toList(); } setState(() { _filteredJournals = results; }); }
修改build方法,加入搜索框并替换列表数据源:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Joost mag het weten'), ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : Column( children: [ // 搜索输入框 Padding( padding: const EdgeInsets.all(12.0), child: TextField( controller: _searchController, onChanged: _filterJournals, decoration: const InputDecoration( labelText: '搜索', prefixIcon: Icon(Icons.search), border: OutlineInputBorder(), ), ), ), // 列表区域,用Expanded避免布局溢出 Expanded( child: ListView.builder( itemCount: _filteredJournals.length, itemBuilder: (context, index) => Card( color: Colors.orange[200], margin: const EdgeInsets.all(15), child: ListTile( leading: Text(_filteredJournals[index]['aantal']), title: Text(_filteredJournals[index]['title']), subtitle: Text(_filteredJournals[index]['description']), trailing: SizedBox( width: 100, child: Row( children: [ IconButton( icon: const Icon(Icons.edit), onPressed: () => _showForm(_filteredJournals[index]['id']), ), IconButton( icon: const Icon(Icons.delete), onPressed: () => _deleteItem(_filteredJournals[index]['id']), ), ], ), )), ), ), ), ], ), floatingActionButton: FloatingActionButton( child: const Icon(Icons.add), onPressed: () => _showForm(null), ), ); }
最后记得在页面销毁时释放控制器:
@override void dispose() { _searchController.dispose(); super.dispose(); }
关键细节说明
- 双列表设计:原始数据只从数据库拉取一次,搜索时直接在内存里过滤,性能更好,适合新手快速实现
- 模糊匹配:过滤时忽略大小写,用户输入大写小写都能匹配到结果
- 布局处理:用Column+Expanded组合,避免搜索框和列表同时存在时出现布局溢出问题
内容的提问来源于stack exchange,提问作者Renzo
相关产品推荐
相关产品推荐

