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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 01:50:25