flutter-searchfield
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFlutter SearchField Implementation
Flutter SearchField 组件实现
SearchField is a highly customizable autocomplete widget for Flutter.
SearchField是一款针对Flutter的高度可定制自动补全组件。
Installation
安装
bash
flutter pub add searchfieldOr add manually to :
pubspec.yamlyaml
dependencies:
searchfield: ^2.0.0dart
import 'package:searchfield/searchfield.dart';bash
flutter pub add searchfield或者手动添加到中:
pubspec.yamlyaml
dependencies:
searchfield: ^2.0.0dart
import 'package:searchfield/searchfield.dart';Quick Start
快速开始
Implementation follows three core steps: initialize suggestions, map to SearchFieldListItem, and add the widget.
实现过程遵循三个核心步骤:初始化建议项、映射为SearchFieldListItem、添加组件。
Step 1: Initialize Suggestions
步骤1:初始化建议项
dart
late List<SearchFieldListItem<YourType>> items;
YourType? selectedValue;
void initState() {
items = yourDataList.map((item) {
return SearchFieldListItem<YourType>(
item.searchableProperty, // Required: search performed on this
value: item.displayValue, // Optional: shown in input on selection
item: item, // Optional: custom object
child: customWidget, // Optional: custom suggestion widget
);
}).toList();
super.initState();
}dart
late List<SearchFieldListItem<YourType>> items;
YourType? selectedValue;
void initState() {
items = yourDataList.map((item) {
return SearchFieldListItem<YourType>(
item.searchableProperty, // 必填:基于该属性执行搜索
value: item.displayValue, // 可选:选中后在输入框中显示的值
item: item, // 可选:自定义对象
child: customWidget, // 可选:自定义建议项组件
);
}).toList();
super.initState();
}Step 2: Add SearchField Widget
步骤2:添加SearchField组件
dart
SearchField<YourType>(
hint: 'Search placeholder',
suggestions: items,
selectedValue: selectedValue,
onSuggestionTap: (SearchFieldListItem<YourType> item) {
setState(() {
selectedValue = item;
});
},
onSearchTextChanged: (query) {
// Return filtered list based on query
if (query.isEmpty) return items;
return items.where((item) =>
item.searchKey.toLowerCase().contains(query.toLowerCase())
).toList();
},
)dart
SearchField<YourType>(
hint: '搜索占位符',
suggestions: items,
selectedValue: selectedValue,
onSuggestionTap: (SearchFieldListItem<YourType> item) {
setState(() {
selectedValue = item;
});
},
onSearchTextChanged: (query) {
// 根据查询条件返回过滤后的列表
if (query.isEmpty) return items;
return items.where((item) =>
item.searchKey.toLowerCase().contains(query.toLowerCase())
).toList();
},
)Common Patterns
常见实现模式
Pattern 1: Basic Text Search
模式1:基础文本搜索
For simple string lists without custom objects:
dart
SearchField(
suggestions: ['Item 1', 'Item 2', 'Item 3']
.map((e) => SearchFieldListItem<String>(e))
.toList(),
suggestionState: Suggestion.expand,
onSuggestionTap: (item) {
// Handle selection
},
)适用于无自定义对象的简单字符串列表:
dart
SearchField(
suggestions: ['Item 1', 'Item 2', 'Item 3']
.map((e) => SearchFieldListItem<String>(e))
.toList(),
suggestionState: Suggestion.expand,
onSuggestionTap: (item) {
// 处理选中逻辑
},
)Pattern 2: Complex Objects with Custom Display
模式2:带自定义展示的复杂对象
When displaying rich content in suggestions:
dart
SearchFieldListItem<City>(
city.name, // Search key
value: city.zipCode, // Value shown in input on select
item: city, // Full object for reference
child: Row( // Custom widget
children: [
Icon(Icons.location_city),
SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(city.name, style: TextStyle(fontWeight: FontWeight.bold)),
Text(city.zipCode, style: TextStyle(fontSize: 12)),
],
),
],
),
)当需要在建议项中展示丰富内容时:
dart
SearchFieldListItem<City>(
city.name, // 搜索关键字
value: city.zipCode, // 选中后在输入框显示的值
item: city, // 用于参考的完整对象
child: Row( // 自定义组件
children: [
Icon(Icons.location_city),
SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(city.name, style: TextStyle(fontWeight: FontWeight.bold)),
Text(city.zipCode, style: TextStyle(fontSize: 12)),
],
),
],
),
)Pattern 3: Network Loading with Pagination
模式3:带分页的网络加载
Load suggestions dynamically from API:
dart
SearchField(
onTap: () async {
// Trigger initial load
final results = await fetchFromAPI();
setState(() => suggestions = results);
},
onSearchTextChanged: (query) {
// Filter or fetch based on query
return filteredSuggestions
.map((e) => SearchFieldListItem<String>(e))
.toList();
},
emptyWidget: Container(
height: 100,
child: Center(
child: CircularProgressIndicator(),
),
),
onScroll: (position, maxScroll) {
// Load more when near bottom
if (position > maxScroll * 0.8) {
loadMoreItems();
}
},
)从API动态加载建议项:
dart
SearchField(
onTap: () async {
// 触发初始加载
final results = await fetchFromAPI();
setState(() => suggestions = results);
},
onSearchTextChanged: (query) {
// 根据查询条件过滤或获取数据
return filteredSuggestions
.map((e) => SearchFieldListItem<String>(e))
.toList();
},
emptyWidget: Container(
height: 100,
child: Center(
child: CircularProgressIndicator(),
),
),
onScroll: (position, maxScroll) {
// 滚动到底部附近时加载更多
if (position > maxScroll * 0.8) {
loadMoreItems();
}
},
)Customization Guide
自定义指南
Input Field Styling
输入框样式
Use for TextField-like customization:
searchInputDecorationdart
searchInputDecoration: SearchInputDecoration(
prefixIcon: Icon(Icons.search),
suffixIcon: Icon(Icons.arrow_drop_down),
hintStyle: TextStyle(color: Colors.grey),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2),
),
filled: true,
fillColor: Colors.grey[100],
)使用实现类似TextField的自定义:
searchInputDecorationdart
searchInputDecoration: SearchInputDecoration(
prefixIcon: Icon(Icons.search),
suffixIcon: Icon(Icons.arrow_drop_down),
hintStyle: TextStyle(color: Colors.grey),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2),
),
filled: true,
fillColor: Colors.grey[100],
)Suggestion List Styling
建议列表样式
Customize the dropdown container:
dart
suggestionsDecoration: SuggestionDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
color: Colors.white,
hoverColor: Colors.grey.shade200,
)自定义下拉容器样式:
dart
suggestionsDecoration: SuggestionDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
color: Colors.white,
hoverColor: Colors.grey.shade200,
)Individual Suggestion Item Styling
单个建议项样式
Style each suggestion item:
dart
suggestionItemDecoration: SuggestionDecoration(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
color: Colors.grey.shade200,
borderRadius: BorderRadius.all(Radius.circular(2)),
)自定义每个建议项的样式:
dart
suggestionItemDecoration: SuggestionDecoration(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
color: Colors.grey.shade200,
borderRadius: BorderRadius.all(Radius.circular(2)),
)Advanced Features
高级功能
Form Validation
表单验证
Integrate with Flutter Forms:
dart
Form(
key: _formKey,
child: SearchField(
suggestions: validOptions.map((e) => SearchFieldListItem(e)).toList(),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please select an option';
}
if (!validOptions.contains(value)) {
return 'Please select a valid option';
}
return null;
},
autovalidateMode: AutovalidateMode.onUserInteraction,
),
)与Flutter表单集成:
dart
Form(
key: _formKey,
child: SearchField(
suggestions: validOptions.map((e) => SearchFieldListItem(e)).toList(),
validator: (value) {
if (value == null || value.isEmpty) {
return '请选择一个选项';
}
if (!validOptions.contains(value)) {
return '请选择有效的选项';
}
return null;
},
autovalidateMode: AutovalidateMode.onUserInteraction,
),
)Keyboard Navigation
键盘导航
Enabled by default for desktop platforms:
- - Navigate suggestions (circular)
↑/↓ - - Jump to last item
Ctrl/Option + ↓ - - Jump to first item
Ctrl/Option + ↑ - - Select highlighted suggestion
Enter - - Close suggestions
Esc
桌面平台默认启用:
- - 循环导航建议项
↑/↓ - - 跳转到最后一项
Ctrl/Option + ↓ - - 跳转到第一项
Ctrl/Option + ↑ - - 选中高亮的建议项
Enter - - 关闭建议列表
Esc
Dynamic Height Suggestions
动态高度建议项
Allow variable height items:
dart
SearchField(
dynamicHeight: true,
maxSuggestionBoxHeight: 400, // Maximum viewport height
suggestions: items.map((item) =>
SearchFieldListItem(
item.name,
child: Container(
// Variable height content
child: Column(
children: [
Text(item.title),
if (item.hasSubtitle) Text(item.subtitle),
],
),
),
),
).toList(),
)支持可变高度的建议项:
dart
SearchField(
dynamicHeight: true,
maxSuggestionBoxHeight: 400, // 最大视口高度
suggestions: items.map((item) =>
SearchFieldListItem(
item.name,
child: Container(
// 可变高度内容
child: Column(
children: [
Text(item.title),
if (item.hasSubtitle) Text(item.subtitle),
],
),
),
),
).toList(),
)Positioning Control
位置控制
Control suggestion list position:
dart
SearchField(
suggestionDirection: SuggestionDirection.up, // Show above input
offset: Offset(0, 10), // Offset from input field
// Direction auto-adjusts based on available space
)控制建议列表的显示位置:
dart
SearchField(
suggestionDirection: SuggestionDirection.up, // 在输入框上方显示
offset: Offset(0, 10), // 与输入框的偏移量
// 会根据可用空间自动调整方向
)Key Properties Reference
核心属性参考
Essential Properties:
- (required) - List of SearchFieldListItem
suggestions - - Callback when suggestion selected
onSuggestionTap - - Filter logic, returns filtered suggestions
onSearchTextChanged - - Currently selected item
selectedValue - - Placeholder text
hint
Display Configuration:
- - Fixed height per item (default: 51.0)
itemHeight - - Enable variable item heights
dynamicHeight - - Max visible items
maxSuggestionsInViewPort - - Max dropdown height (with dynamicHeight)
maxSuggestionBoxHeight
Behavior:
- - Controls initial suggestion visibility:
suggestionState- — Show suggestions immediately when the field is focused (common for dropdown-style pickers)
Suggestion.expand - — Show suggestions only after the user starts typing (common for search-style inputs)
Suggestion.hidden
- - Enable autocorrect (default: true)
autoCorrect - - Enable/disable widget (default: true)
enabled - - Make input read-only (default: false)
readOnly - - Keep search text in the field after selecting a suggestion (default: false)
keepSearchOnSelection - - Keyboard action button
textInputAction - - Configures keyboard uppercase/lowercase behavior
textCapitalization - - Alignment of the text in the searchfield (default: TextAlign.start)
textAlign - - Input formatters for the search field
inputFormatters - - Enum to control focus behavior on suggestion tap
SuggestionAction
Callbacks:
- - When field gains focus
onTap - - When form submitted
onSubmit - - When tapping outside
onOutsideTap - - Scroll position updates (for pagination)
onScroll - - Boolean to show/hide the emptyWidget
showEmpty
Styling:
- - Input field decoration
searchInputDecoration - - Dropdown container decoration
suggestionsDecoration - - Individual item decoration
suggestionItemDecoration - - Text style for input
searchStyle - - Text style for suggestions
suggestionStyle - - Decoration for the scrollbar
scrollbarDecoration - - Color for the margin between suggestions
marginColor
Controllers:
- - TextEditingController
controller - - FocusNode for focus management
focusNode - - Control suggestion list scroll
scrollController
必备属性:
- (必填)- SearchFieldListItem列表
suggestions - - 选中建议项时的回调
onSuggestionTap - - 过滤逻辑,返回过滤后的建议项
onSearchTextChanged - - 当前选中的项
selectedValue - - 占位符文本
hint
显示配置:
- - 每个项的固定高度(默认:51.0)
itemHeight - - 启用可变项高度
dynamicHeight - - 最大可见项数量
maxSuggestionsInViewPort - - 下拉框最大高度(配合dynamicHeight使用)
maxSuggestionBoxHeight
行为配置:
- - 控制建议列表初始可见性:
suggestionState- — 输入框获得焦点时立即显示建议列表(常见于下拉选择器)
Suggestion.expand - — 仅在用户开始输入后显示建议列表(常见于搜索式输入框)
Suggestion.hidden
- - 启用自动校正(默认:true)
autoCorrect - - 启用/禁用组件(默认:true)
enabled - - 设置输入框为只读(默认:false)
readOnly - - 选中建议项后保留搜索文本在输入框中(默认:false)
keepSearchOnSelection - - 键盘操作按钮
textInputAction - - 配置键盘大小写行为
textCapitalization - - 输入框中文本对齐方式(默认:TextAlign.start)
textAlign - - 输入框的输入格式化器
inputFormatters - - 枚举类型,控制选中建议项时的焦点行为
SuggestionAction
回调函数:
- - 输入框获得焦点时触发
onTap - - 表单提交时触发
onSubmit - - 点击外部区域时触发
onOutsideTap - - 滚动位置更新时触发(用于分页)
onScroll - - 控制是否显示emptyWidget的布尔值
showEmpty
样式配置:
- - 输入框装饰
searchInputDecoration - - 下拉容器装饰
suggestionsDecoration - - 单个项的装饰
suggestionItemDecoration - - 输入框文本样式
searchStyle - - 建议项文本样式
suggestionStyle - - 滚动条装饰
scrollbarDecoration - - 建议项之间的间距颜色
marginColor
控制器:
- - TextEditingController
controller - - 用于焦点管理的FocusNode
focusNode - - 控制建议列表的滚动
scrollController
Common Issues
常见问题
Issue: Suggestions not filtering
问题:建议项无法过滤
Cause: not returning filtered list
onSearchTextChangedSolution: Always return a filtered List<SearchFieldListItem> from :
onSearchTextChangeddart
onSearchTextChanged: (query) {
if (query.isEmpty) return allSuggestions;
return allSuggestions.where((item) {
return item.searchKey.toLowerCase().contains(query.toLowerCase());
}).toList();
}原因:未返回过滤后的列表
onSearchTextChanged解决方案:确保始终返回过滤后的List<SearchFieldListItem>:
onSearchTextChangeddart
onSearchTextChanged: (query) {
if (query.isEmpty) return allSuggestions;
return allSuggestions.where((item) {
return item.searchKey.toLowerCase().contains(query.toLowerCase());
}).toList();
}Issue: Selected value not displaying
问题:选中的值不显示
Cause: Not updating in setState
selectedValueSolution: Update state in onSuggestionTap:
dart
onSuggestionTap: (item) {
setState(() {
selectedValue = item;
});
}原因:未在setState中更新
selectedValue解决方案:在onSuggestionTap中更新状态:
dart
onSuggestionTap: (item) {
setState(() {
selectedValue = item;
});
}Issue: Form validation not working
问题:表单验证不生效
Cause: SearchField not wrapped in Form or missing validator
Solution: Ensure Form wrapper and provide validator:
dart
Form(
key: _formKey,
child: SearchField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Required field';
}
return null;
},
),
)原因:SearchField未包裹在Form中,或缺少validator
解决方案:确保使用Form包裹,并提供验证器:
dart
Form(
key: _formKey,
child: SearchField(
validator: (value) {
if (value == null || value.isEmpty) {
return '必填项';
}
return null;
},
),
)Example Code References
示例代码参考
For complete examples, see: