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

点击搜索框X按钮后,SearchAnchor的suggestionBuilder不更新问题

问题:点击搜索框清除按钮后建议列表未更新

点击搜索框中的X按钮清除用户输入后,建议列表未更新。该按钮的onPressed逻辑在viewTrailing中实现,但调试发现点击后suggestionBuilder未被调用,请问原因是什么?

class _SearchAnchor extends StatefulWidget {
  const _SearchAnchor({
    super.key,
  });

  @override
  State<_SearchAnchor> createState() => _SearchAnchorState();
}

class _SearchAnchorState extends State<_SearchAnchor> {
  List<BaseUser> filteredEmployees = [];
  final searchController = SearchController();

  @override
  Widget build(BuildContext context) {
    final availableEmployees = context
        .select((ShiftFormCubit cubit) => cubit.state.availableEmployees);
    // Initialize the filteredEmployees list with all available employees.
    // This ensures that all employees are shown when the widget is first displayed.
    if (filteredEmployees.isEmpty && availableEmployees.isNotEmpty) {
      filteredEmployees = List.from(availableEmployees);
    }
    return SearchAnchor(
        searchController: searchController,
        viewConstraints: const BoxConstraints(
          maxHeight: 200.0,
          maxWidth: 250.0,
        ),
        builder: (BuildContext context, SearchController searchController) {
          return SizedBox(
            width: 250.0,
            child: SearchBar(
              controller: searchController,
              padding: const MaterialStatePropertyAll<EdgeInsets>(
                  EdgeInsets.symmetric(horizontal: 16.0)),
              onTap: () {
                searchController.openView();
              },
              leading: const Icon(Icons.search),
            ),
          );
        },
        suggestionsBuilder:
            (BuildContext context, SearchController controller) {
          return filteredEmployees.map((employee) {
            return ListTile(
              title: Text(employee.name),
              onTap: () {
                setState(() {
                  controller.closeView(employee.name);
                });
              },
            );
          });
        },
        viewOnChanged: (value) {
          setState(() {
            filteredEmployees = availableEmployees
                .where((element) =>
                    element.name.toLowerCase().contains(value.toLowerCase()))
                .toList();
          });
        },
        viewTrailing: [
          IconButton(
            icon: const Icon(Icons.close),
            onPressed: () {
              setState(() {
                searchController.clear();
                filteredEmployees = List.from(availableEmployees);
              });
            },
          )
        ]);
  }
}

原因分析

  1. searchController.clear()不会触发viewOnChanged回调——这是之前驱动建议列表更新的核心逻辑,没有这个触发,SearchAnchor不会主动调用suggestionBuilder
  2. 虽然你在setState里更新了filteredEmployees,但SearchAnchor的建议列表并不依赖State的刷新自动重建,它只响应searchController的状态变化或者viewOnChanged的调用
  3. 手动调用clear()后,SearchAnchor内部没有感知到需要重新渲染建议列表,所以suggestionBuilder不会执行

修复方案

方案一:手动通知刷新

在clear()后调用searchController.notifyListeners(),强制通知SearchAnchor更新建议列表:

viewTrailing: [
  IconButton(
    icon: const Icon(Icons.close),
    onPressed: () {
      setState(() {
        searchController.clear();
        filteredEmployees = List.from(availableEmployees);
        // 强制通知刷新
        searchController.notifyListeners();
      });
    },
  )
]

方案二:复用过滤逻辑

先把过滤逻辑抽成独立方法,再在viewTrailing和viewOnChanged中复用,确保逻辑一致性并触发刷新:

// 抽离过滤逻辑
List<BaseUser> _filterEmployees(String query, List<BaseUser> available) {
  return available
      .where((element) =>
          element.name.toLowerCase().contains(query.toLowerCase()))
      .toList();
}

// 更新viewOnChanged和viewTrailing
viewOnChanged: (value) {
  setState(() {
    filteredEmployees = _filterEmployees(value, availableEmployees);
  });
},
viewTrailing: [
  IconButton(
    icon: const Icon(Icons.close),
    onPressed: () {
      setState(() {
        searchController.clear();
        filteredEmployees = _filterEmployees('', availableEmployees);
      });
      searchController.notifyListeners();
    },
  )
]

额外优化:修复初始化逻辑

你在build方法里初始化filteredEmployees的逻辑可能导致状态不一致,建议移到didChangeDependencies中:

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  final availableEmployees = context.select((ShiftFormCubit cubit) => cubit.state.availableEmployees);
  if (filteredEmployees.isEmpty && availableEmployees.isNotEmpty) {
    filteredEmployees = List.from(availableEmployees);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 01:30:22