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

Flutter中如何基于ListView索引实现筛选搜索功能?

解决ListView搜索过滤问题:输入“z”时列表无内容

嘿,我来帮你搞定这个搜索功能的问题!目前你的代码里缺少了根据搜索文本过滤列表数据的核心逻辑,所以搜索功能没法正常生效。咱们一步步来修复:

核心思路

  • 维护一个filteredTicketDetails列表,专门存储符合搜索条件的工单数据
  • 实现onSearchTextChanged方法,根据输入文本过滤原列表returnTicketDetails,匹配用户的姓名信息
  • 让ListView基于过滤后的列表渲染,而不是直接用原数据

修改后的完整代码

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';

// 假设你有全局的access_token变量
String access_token = "your_access_token_here";

class TicketScreen extends StatefulWidget {
  @override
  _TicketScreenState createState() => _TicketScreenState();
}

class _TicketScreenState extends State<TicketScreen> {
  final TextEditingController controller = TextEditingController();
  Map userDetails = {};
  List returnTicketDetails = [];
  // 新增:存储过滤后的工单数据
  List filteredTicketDetails = [];

  @override
  void initState() {
    super.initState();
    _getTicketDetails();
  }

  void onSearchTextChanged(String text) {
    setState(() {
      if (text.isEmpty) {
        // 搜索框为空时,显示全部数据
        filteredTicketDetails = List.from(returnTicketDetails);
      } else {
        // 根据用户姓名过滤数据(不区分大小写)
        filteredTicketDetails = returnTicketDetails.where((ticket) {
          String firstName = userDetails[ticket["user_id"]]["first_name"].toLowerCase();
          String lastName = userDetails[ticket["user_id"]]["last_name"].toLowerCase();
          return firstName.contains(text.toLowerCase()) || lastName.contains(text.toLowerCase());
        }).toList();
      }
    });
  }

  _getTicketDetails() async {
    final response = await http.get(
      Uri.parse("https://your-api-url/tickets"), // 替换成实际API地址
      headers: {HttpHeaders.AUTHORIZATION: access_token},
    );
    returnTicketDetails = json.decode(response.body);
    // 初始化过滤列表为全部数据
    filteredTicketDetails = List.from(returnTicketDetails);

    for (var i = 0; i < (returnTicketDetails?.length ?? 0); i++) {
      final ticketresponse = await http.get(
        Uri.parse("https://your-api-url/users/${returnTicketDetails[i]["user_id"]}"), // 替换成实际用户API地址
        headers: {HttpHeaders.AUTHORIZATION: access_token},
      );
      userDetails[returnTicketDetails[i]["user_id"]] = json.decode(ticketresponse.body);
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[
          Container(
            color: Theme.of(context).primaryColor,
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Card(
                child: ListTile(
                  leading: Icon(Icons.search),
                  title: TextField(
                    controller: controller,
                    decoration: InputDecoration(
                      hintText: 'Search',
                      border: InputBorder.none,
                    ),
                    // 绑定搜索回调
                    onChanged: onSearchTextChanged,
                  ),
                  trailing: IconButton(
                    icon: Icon(Icons.cancel),
                    onPressed: () {
                      controller.clear();
                      onSearchTextChanged('');
                    },
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            child: filteredTicketDetails.isNotEmpty
                ? ListView.builder(
                    itemCount: filteredTicketDetails.length,
                    itemBuilder: (context, index) {
                      var ticket = filteredTicketDetails[index];
                      var user = userDetails[ticket["user_id"]];
                      return Card(
                        child: Column(
                          mainAxisSize: MainAxisSize.min,
                          children: <Widget>[
                            Row(
                              children: <Widget>[
                                Container(
                                  width: 80.0,
                                  height: 80.0,
                                  decoration: BoxDecoration(
                                    shape: BoxShape.circle,
                                    image: DecorationImage(
                                      fit: BoxFit.fill,
                                      image: NetworkImage("https://your-image-url.com"), // 替换成实际头像地址
                                    ),
                                  ),
                                ),
                                Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    Text(user["first_name"]),
                                    Text(user["last_name"]),
                                  ],
                                ),
                              ],
                            ),
                          ],
                        ),
                      );
                    },
                  )
                : Center(
                    // 过滤后无数据时显示提示
                    child: Text("没有找到匹配的内容"),
                  ),
          ),
        ],
      ),
    );
  }
}

关键说明

  • 过滤逻辑:在onSearchTextChanged里,我们把用户名字和输入文本都转成小写再匹配,这样搜索不区分大小写,体验更友好
  • ListView渲染:现在完全基于filteredTicketDetails构建,当输入“z”但没有用户名字包含z时,这个列表会是空的,页面会显示“没有找到匹配的内容”的提示(你也可以自定义空状态UI)
  • 初始化处理:获取到工单数据后,把filteredTicketDetails初始化为全部数据,保证页面加载时显示完整列表

这样修改后,你的搜索功能就能正常工作啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:42:43