flutter-searchfield
npx skills add https://github.com/maheshj01/skills --skill flutter-searchfield
Agent 安装分布
Skill 文档
Flutter SearchField Implementation
SearchField is a highly customizable autocomplete widget for Flutter.
Installation
flutter pub add searchfield
Or add manually to pubspec.yaml:
dependencies:
searchfield: ^2.0.0
import 'package:searchfield/searchfield.dart';
Quick Start
Implementation follows three core steps: initialize suggestions, map to SearchFieldListItem, and add the widget.
Step 1: Initialize Suggestions
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();
}
Step 2: Add SearchField Widget
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();
},
)
Common Patterns
Pattern 1: Basic Text Search
For simple string lists without custom objects:
SearchField(
suggestions: ['Item 1', 'Item 2', 'Item 3']
.map((e) => SearchFieldListItem<String>(e))
.toList(),
suggestionState: Suggestion.expand,
onSuggestionTap: (item) {
// Handle selection
},
)
Pattern 2: Complex Objects with Custom Display
When displaying rich content in suggestions:
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)),
],
),
],
),
)
Pattern 3: Network Loading with Pagination
Load suggestions dynamically from API:
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();
}
},
)
Customization Guide
Input Field Styling
Use searchInputDecoration for TextField-like customization:
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:
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:
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:
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,
),
)
Keyboard Navigation
Enabled by default for desktop platforms:
â/â– Navigate suggestions (circular)Ctrl/Option + â– Jump to last itemCtrl/Option + â– Jump to first itemEnter– Select highlighted suggestionEsc– Close suggestions
Dynamic Height Suggestions
Allow variable height items:
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(),
)
Positioning Control
Control suggestion list position:
SearchField(
suggestionDirection: SuggestionDirection.up, // Show above input
offset: Offset(0, 10), // Offset from input field
// Direction auto-adjusts based on available space
)
Key Properties Reference
Essential Properties:
suggestions(required) – List of SearchFieldListItemonSuggestionTap– Callback when suggestion selectedonSearchTextChanged– Filter logic, returns filtered suggestionsselectedValue– Currently selected itemhint– Placeholder text
Display Configuration:
itemHeight– Fixed height per item (default: 51.0)dynamicHeight– Enable variable item heightsmaxSuggestionsInViewPort– Max visible itemsmaxSuggestionBoxHeight– Max dropdown height (with dynamicHeight)
Behavior:
suggestionState– Controls initial suggestion visibility:Suggestion.expandâ Show suggestions immediately when the field is focused (common for dropdown-style pickers)Suggestion.hiddenâ Show suggestions only after the user starts typing (common for search-style inputs)
autoCorrect– Enable autocorrect (default: true)enabled– Enable/disable widget (default: true)readOnly– Make input read-only (default: false)keepSearchOnSelection– Keep search text in the field after selecting a suggestion (default: false)textInputAction– Keyboard action buttontextCapitalization– Configures keyboard uppercase/lowercase behaviortextAlign– Alignment of the text in the searchfield (default: TextAlign.start)inputFormatters– Input formatters for the search fieldSuggestionAction– Enum to control focus behavior on suggestion tap
Callbacks:
onTap– When field gains focusonSubmit– When form submittedonOutsideTap– When tapping outsideonScroll– Scroll position updates (for pagination)showEmpty– Boolean to show/hide the emptyWidget
Styling:
searchInputDecoration– Input field decorationsuggestionsDecoration– Dropdown container decorationsuggestionItemDecoration– Individual item decorationsearchStyle– Text style for inputsuggestionStyle– Text style for suggestionsscrollbarDecoration– Decoration for the scrollbarmarginColor– Color for the margin between suggestions
Controllers:
controller– TextEditingControllerfocusNode– FocusNode for focus managementscrollController– Control suggestion list scroll
Common Issues
Issue: Suggestions not filtering
Cause: onSearchTextChanged not returning filtered list
Solution: Always return a filtered List from onSearchTextChanged:
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 selectedValue in setState
Solution: Update state in onSuggestionTap:
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:
Form(
key: _formKey,
child: SearchField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Required field';
}
return null;
},
),
)
Example Code References
For complete examples, see: