Flutter:如何用TextField组件实现带联想结果的搜索栏
实现带联想搜索的自定义搜索栏
要实现输入时显示联想搜索结果的自定义搜索栏,你可以基于现有的TextField,通过状态管理+实时过滤数据源来完成,具体步骤和代码如下:
核心思路
- 用
StatefulWidget管理输入内容和联想结果的状态 - 监听TextField的输入变化,实时过滤预设/接口返回的数据源
- 将TextField与联想结果列表组合在同一布局中,根据输入内容动态显示/隐藏结果
完整实现代码
import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; class CustomSearchBar extends StatefulWidget { const CustomSearchBar({super.key}); @override State<CustomSearchBar> createState() => _CustomSearchBarState(); } class _CustomSearchBarState extends State<CustomSearchBar> { // 模拟搜索数据源(实际项目可替换为接口请求) final List<String> _allItems = [ "Apple", "Banana", "Orange", "Apple Pie", "Banana Bread", "Orange Juice", "Grape", "Grape Juice" ]; late List<String> _filteredItems; final TextEditingController _searchController = TextEditingController(); @override void initState() { super.initState(); _filteredItems = []; // 监听输入变化(也可以用TextField的onChanged) _searchController.addListener(_filterItems); } @override void dispose() { _searchController.dispose(); super.dispose(); } // 根据输入文本过滤数据源 void _filterItems() { final query = _searchController.text.toLowerCase(); setState(() { if (query.isEmpty) { _filteredItems = []; } else { _filteredItems = _allItems .where((item) => item.toLowerCase().contains(query)) .toList(); } }); } @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ // 你的原有搜索TextField SizedBox( height: 45, width: 360, child: TextField( controller: _searchController, style: GoogleFonts.poppins( color: const Color(0xff020202), fontSize: 20, fontWeight: FontWeight.w400, letterSpacing: 0.5, ), decoration: InputDecoration( filled: true, fillColor: const Color(0xfff1f1f1), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), hintText: "Search for Items", hintStyle: GoogleFonts.poppins( color: const Color(0xffb2b2b2), fontSize: 20, fontWeight: FontWeight.w400, letterSpacing: 0.5, decorationThickness: 6), prefixIcon: const Icon(Icons.search), prefixIconColor: Colors.black, ), ), ), // 联想搜索结果列表 if (_filteredItems.isNotEmpty) Container( width: 360, margin: const EdgeInsets.only(top: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), blurRadius: 4, offset: const Offset(0, 2), ) ], ), child: ListView.builder( shrinkWrap: true, padding: EdgeInsets.zero, itemCount: _filteredItems.length, itemBuilder: (context, index) { final item = _filteredItems[index]; return ListTile( title: Text( item, style: GoogleFonts.poppins(fontSize: 18), ), onTap: () { // 点击联想项后的操作:填充到搜索框/直接搜索 setState(() { _searchController.text = item; _filteredItems = []; }); // 这里可以添加跳转搜索结果页等逻辑 }, ); }, ), ), ], ); } }
关键说明
- 状态管理:通过
TextEditingController监听输入变化,或者直接使用TextField的onChanged回调,两种方式都能实时获取输入文本 - 数据源过滤:将输入文本转为小写后与数据源项匹配,确保搜索不区分大小写
- 布局控制:用
if判断控制联想列表的显示,只有当输入有内容且过滤到结果时才展示,列表使用shrinkWrap: true避免占用过多空间 - 交互优化:点击联想项后自动填充到搜索框并隐藏结果列表,也可根据需求改为直接触发搜索请求
内容的提问来源于stack exchange,提问作者Divya
相关产品推荐
相关产品推荐

