You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
}

关键细节说明

  1. 双列表设计:原始数据只从数据库拉取一次,搜索时直接在内存里过滤,性能更好,适合新手快速实现
  2. 模糊匹配:过滤时忽略大小写,用户输入大写小写都能匹配到结果
  3. 布局处理:用Column+Expanded组合,避免搜索框和列表同时存在时出现布局溢出问题

内容的提问来源于stack exchange,提问作者Renzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 16:05:41