点击搜索框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); }); }, ) ]); } }
原因分析
searchController.clear()不会触发viewOnChanged回调——这是之前驱动建议列表更新的核心逻辑,没有这个触发,SearchAnchor不会主动调用suggestionBuilder- 虽然你在
setState里更新了filteredEmployees,但SearchAnchor的建议列表并不依赖State的刷新自动重建,它只响应searchController的状态变化或者viewOnChanged的调用 - 手动调用
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
相关产品推荐
相关产品推荐

