Flutter开发求助:如何用搜索栏过滤API返回的列表数据
Flutter 实现搜索过滤列表
实现步骤
- 添加搜索输入框与状态管理,实时响应搜索文本并过滤数据
- 维护两个列表:一个存储API返回的原始产品数据,另一个存储过滤后的结果
- 监听搜索框输入,动态更新过滤后的列表
完整代码示例
import 'package:flutter/material.dart'; // 请根据实际API返回结构调整你的Product模型类 class Product { final String title; final String image; Product({required this.title, required this.image}); } class FilterableProductList extends StatefulWidget { const FilterableProductList({super.key}); @override State<FilterableProductList> createState() => _FilterableProductListState(); } class _FilterableProductListState extends State<FilterableProductList> { final TextEditingController _searchController = TextEditingController(); List<Product>? _originalProducts; // 存储API返回的原始数据 List<Product>? _filteredProducts; // 存储过滤后的展示数据 @override void initState() { super.initState(); // 此处替换为你的API请求逻辑,获取数据后赋值给_originalProducts _originalProducts = [ Product(title: "无线蓝牙耳机", image: "https://example.com/bt.jpg"), Product(title: "智能运动手表", image: "https://example.com/watch.jpg"), Product(title: "快充移动电源", image: "https://example.com/power.jpg"), ]; _filteredProducts = _originalProducts; _searchController.addListener(_filterProducts); } // 核心过滤逻辑:根据搜索文本匹配产品标题 void _filterProducts() { final searchText = _searchController.text.toLowerCase(); if (searchText.isEmpty) { setState(() => _filteredProducts = _originalProducts); return; } setState(() { _filteredProducts = _originalProducts?.where((product) => product.title.toLowerCase().contains(searchText)).toList(); }); } @override void dispose() { _searchController.dispose(); // 销毁控制器避免内存泄漏 super.dispose(); } @override Widget build(BuildContext context) { return Column( children: [ // 搜索输入框 Padding( padding: const EdgeInsets.all(16.0), child: TextField( controller: _searchController, decoration: const InputDecoration( hintText: "搜索产品...", prefixIcon: Icon(Icons.search), border: OutlineInputBorder(), ), ), ), // 过滤后的产品列表 Expanded( child: ListView.builder( shrinkWrap: true, itemCount: _filteredProducts?.length ?? 0, physics: const AlwaysScrollableScrollPhysics(), itemBuilder: (context, index) { final product = _filteredProducts![index]; return Padding( padding: const EdgeInsets.only(left: 15), child: ListTile( title: Text(product.title), leading: CircleAvatar( backgroundImage: NetworkImage(product.image), ), ), ); }, ), ), ], ); } }
关键说明
- 移除了你原代码中
Expanded包裹ListTile的写法:ListView.builder的item无需Expanded,否则会引发布局异常 - 用
_filteredProducts作为列表数据源,确保展示内容为过滤后的结果 - 搜索逻辑默认做了不区分大小写的标题匹配,你可以根据需求修改匹配规则(比如匹配产品描述、ID等)
- 实际开发时,把示例中的模拟数据替换为你的API请求逻辑即可
内容的提问来源于stack exchange,提问作者Alghubs
相关产品推荐
相关产品推荐

