Flutter中如何让SearchBar下方显示建议列表?
问题描述
我想要实现Flutter官方SearchBar示例中的效果,让建议列表显示在SearchBar下方(建议项出现在搜索框正下方),但使用示例代码后,点击SearchBar时搜索框和列表会全屏展示。我的代码如下:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Add game'), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { Navigator.pop(context); }, ), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SearchAnchor( builder: (BuildContext context, SearchController controller) { return SearchBar( controller: controller, padding: const MaterialStatePropertyAll<EdgeInsets>( EdgeInsets.symmetric(horizontal: 16.0), ), onTap: () { controller.openView(); }, onChanged: (value) { setState(() { // Update the searchText and button enabled state. searchText = value; isButtonEnabled = searchText.isNotEmpty; }); controller.openView(); }, leading: const Icon(Icons.search), ); }, suggestionsBuilder: (BuildContext context, SearchController controller) { return List<ListTile>.generate(5, (int index) { final String item = 'item $index'; return ListTile( title: Text(item), onTap: () { setState(() { controller.closeView(item); }); }, ); }); }, ), const SizedBox(height: 16), ElevatedButton( onPressed: isButtonEnabled ? () => onAddToWatchlistClicked() : null, style: ElevatedButton.styleFrom( backgroundColor: lightColorScheme.primary ), child: const Text('Add to watchlist'), ), ], ), ), ); }
我尝试移除其他子组件,仅保留SearchAnchor也无效,请问我遗漏了什么?
解决方案
问题出在SearchAnchor的默认行为:当它放置在Scaffold的body区域时,默认会触发全屏的搜索视图。要实现官方示例中搜索框下方弹出建议列表的效果,有两种简洁的解决方式:
方式一:使用SearchAnchor.bar构造函数(推荐)
这个构造函数专门设计用于生成下拉式的建议框,无需手动定位,直接贴合需求:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Add game'), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => Navigator.pop(context), ), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SearchAnchor.bar( barHintText: '搜索', controller: SearchController(), suggestionsBuilder: (context, controller) { return List<ListTile>.generate(5, (index) { final String item = 'item $index'; return ListTile( title: Text(item), onTap: () { setState(() { controller.closeView(item); searchText = item; isButtonEnabled = true; }); }, ); }); }, ), const SizedBox(height: 16), ElevatedButton( onPressed: isButtonEnabled ? () => onAddToWatchlistClicked() : null, style: ElevatedButton.styleFrom( backgroundColor: lightColorScheme.primary ), child: const Text('Add to watchlist'), ), ], ), ), ); }
方式二:自定义viewBuilder控制弹出层
如果需要更灵活的样式控制,可以通过viewBuilder手动定位建议列表:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Add game'), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => Navigator.pop(context), ), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Builder( builder: (context) { return SearchAnchor( viewBuilder: (context, controller, child) { return Positioned( top: 80, // 根据实际布局调整搜索框下方的距离 left: 16, right: 16, child: Material( elevation: 4, borderRadius: BorderRadius.circular(8), child: SizedBox( height: 200, child: ListView.builder( itemCount: 5, itemBuilder: (context, index) { final String item = 'item $index'; return ListTile( title: Text(item), onTap: () { setState(() { controller.closeView(item); searchText = item; isButtonEnabled = true; }); }, ); }, ), ), ), ); }, builder: (BuildContext context, SearchController controller) { return SearchBar( controller: controller, padding: const MaterialStatePropertyAll<EdgeInsets>( EdgeInsets.symmetric(horizontal: 16.0), ), onTap: () => controller.openView(), onChanged: (value) { setState(() { searchText = value; isButtonEnabled = searchText.isNotEmpty; }); controller.openView(); }, leading: const Icon(Icons.search), ); }, ); }, ), const SizedBox(height: 16), ElevatedButton( onPressed: isButtonEnabled ? () => onAddToWatchlistClicked() : null, style: ElevatedButton.styleFrom( backgroundColor: lightColorScheme.primary ), child: const Text('Add to watchlist'), ), ], ), ), ); }
核心说明
SearchAnchor.bar是官方提供的快捷实现,默认生成下拉式建议框,代码更简洁。- 自定义
viewBuilder时,需要用Builder包裹以获取正确上下文,通过Positioned组件精准控制建议列表的位置。
内容的提问来源于stack exchange,提问作者Tashila Pathum
相关产品推荐
相关产品推荐

