Searchfield
A highly customizable simple and easy to use autocomplete widget to your Flutter Application.This Widget allows you to search and select from list of suggestions.
Install / Use
/learn @maheshj01/SearchfieldREADME
searchfield: ^2.0.0
<a href="https://github.com/maheshj01/searchfield" rel="noopener" target="_blank"><img src="https://img.shields.io/badge/platform-flutter-ff69b4.svg" alt="Flutter Platform Badge"></a>
<a href="https://pub.dev/packages/searchfield"><img src="https://img.shields.io/pub/v/searchfield.svg" alt="Pub"></a>
<a href="https://pub.dev/packages/searchfield/versions/1.3.0-dev.3" target="_blank">
<img src="https://img.shields.io/badge/pub-Prerelease--1.3.0--dev.3-blue" alt="Prerelease" />
</a>
<a href="https://opensource.org/licenses/MIT" rel="noopener" target="_blank"><img src="https://img.shields.io/badge/license-MIT-purple.svg" alt="MIT License Badge"></a>
<a href="https://github.com/sponsors/maheshj01/" target="_blank">
<img src="https://img.shields.io/badge/Sponsor-Searchfield-orange" alt="Sponsor @maheshj01" />
</a>
⭐️Show some ❤️ and star the repo.⭐
A highly customizable, simple and easy to use AutoComplete widget for your Flutter app. This widget allows you to
- search 🔍 and select from a list of suggestions
- validate the input with custom validation logic.
- Dynamic height of each suggestion item.
- show suggestions as a custom widget
- Map a custom value to the suggestion list item.
- lazy load the suggestions from Network with custom Loading widget
- show dynamic suggestions above or below the input field
- define max number of items visible in the viewport 📱
- filter out the suggestions with a custom logic
- visually customize the input and the suggestions
- navigate through the suggestions using keyboard for Desktop 🖥 ️
- Listen to scroll events of suggestions
Getting Started
Installation
- Add the dependency
flutter pub add searchfield
- Import the package
import 'package:searchfield/searchfield.dart';
Use the Widget in three steps
Step 1: Initialize your suggestions of any Type
late List<SearchFieldListItem<City>> cities;
SearchFieldListItem<City>? selectedValue;
@override
void initState() {
cities = [
City('New York', '10001'),
City('Los Angeles', '90001'),
...
]
super.initState();
}
Step 2: Map the suggestions to SearchFieldListItem
see SearchFieldListItem to know more about the properties
@override
void initState() {
cities = [
City('New York', '10001'),
City('Los Angeles', '90001'),
...
].map(
(City ct) {
return SearchFieldListItem<City>(
// search will be performed on this value
ct.name,
// value to set in input on click, defaults to searchKey (optional)
value: ct.zip.toString(),
// custom object to pass in the suggestion list (optional)
item: ct,
// custom widget to show in the suggestion list (optional)
child: searchChild(ct, isSelected: false),
);
},
).toList();
super.initState();
}
Step 3: Add SearchField to your widget tree
SearchField(
hint: 'Search for a city or zip code',
maxSuggestionBoxHeight: 300,
onSuggestionTap: (SearchFieldListItem<City> item) {
setState(() {
selectedValue = item;
});
},
onSearchTextChanged: (searchText) {
if (searchText.isEmpty) {
return cities
}
// filter the list with your custom search logic
final filter = List<SearchFieldListItem<City>>.from(cities)
.where((city) {
return city.item!.name
.toLowerCase()
.contains(searchText.toLowerCase()) ||
city.item!.zip.toString().contains(searchText);
}).toList();
return filter;
},
selectedValue: selectedValue,
suggestions: cities,
suggestionState: Suggestion.expand,
),
Customizing the Search Input
SearchField(
hint: 'Search for a city or zip code',
maxSuggestionBoxHeight: 300,
onSuggestionTap: (SearchFieldListItem<City> item) {
setState(() {
selectedValue = item;
});
},
selectedValue: selectedValue,
...
/// customize the search input with wide range of properties
/// through SearchInputDecoration
searchInputDecoration: SearchInputDecoration(
prefixIcon: Icon(Icons.search),
suffix: Icon(Icons.expand_more),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
...
),
),
Customizing the Suggestions List
SearchField(
hint: 'Search for a city or zip code',
maxSuggestionBoxHeight: 300,
onSuggestionTap: (SearchFieldListItem<City> item) {
setState(() {
selectedValue = item;
});
},
selectedValue: selectedValue,
...
/// customize the decoration of the suggestions list
suggestionsDecoration: SuggestionDecoration(
border: Border.all(color: Colors.grey),
hoverColor: Colors.grey.shade200,
borderRadius: BorderRadius.all(Radius.circular(2)),
),
),
Customizing the Suggestions Item
SearchField(
hint: 'Search for a city or zip code',
maxSuggestionBoxHeight: 300,
onSuggestionTap: (SearchFieldListItem<City> item) {
setState(() {
selectedValue = item;
});
},
selectedValue: selectedValue,
...
/// customizes the decoration of each suggestion item
suggestionItemDecoration: SuggestionDecoration(
padding: EdgeInsets.all(8),
borderRadius: BorderRadius.all(Radius.circular(2)),
color: Colors.grey.shade200,
),
),
Example 2 (Network demo)
Ability to load suggestions from the network with a custom loading widget
SearchField(
onSearchTextChanged: (query) {
final filter = suggestions
.where((element) =>
element.toLowerCase().contains(query.toLowerCase()))
.toList();
return filter
.map((e) =>
SearchFieldListItem<String>(e, child: searchChild(e)))
.toList();
},
onTap: () async {
final result = await getSuggestions();
setState(() {
suggestions = result;
});
},
/// widget to show when suggestions are empty
emptyWidget: Container(
decoration: suggestionDecoration,
height: 200,
child: const Center(
child: CircularProgressIndicator(
color: Colors.white,
))),
hint: 'Load suggestions from network',
itemHeight: 50,
scrollbarDecoration: ScrollbarDecoration(),
suggestionStyle: const TextStyle(fontSize: 24, color: Colors.white),
searchInputDecoration: SearchInputDecoration(...),
border: OutlineInputBorder(...)
fillColor: Colors.white,
filled: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 20,
)),
suggestionsDecoration: suggestionDecoration,
suggestions: suggestions
.map((e) => SearchFieldListItem<String>(e, child: searchChild(e)))
.toList(),
focusNode: focus,
suggestionState: Suggestion.expand,
onSuggestionTap: (SearchFieldListItem<String> x) {
},
),
<img src="https://github.com/maheshj01/searchfield/assets/31410839/f4f17c24-63c4-4ec3-9b3b-d27f5ee4575d" width="210"/>
Example 3 Custom Widgets
Example 4 Load suggestions from network with Pagination
Note that this also maintains the Scroll position when new items are added to list see: complete code here
Example 5 (Validation)
Form(
key: _formKey,
child: SearchField(
suggestions: _statesOfIndia
.map((e) => SearchFieldListItem(e))
.toList(),
suggestionState: Suggestion.expand,
textInputAction: TextInputAction.next,
hint: 'SearchField Example 2',
searchStyle: TextStyle(
fontSize: 18,
color: Colors.black.withValues(alpha: 0.8),
),
validator: (x) {
if (!_statesOfIndia.contains(x) || x!.isEmpty) {
return 'Please Enter a valid State';
}
return null;
},
selectedValue: selectedValue,
onSuggestionTap: (SearchFieldListItem<Country> x) {
setState(() {
selectedValue = x.item;
});
},
searchInputDecoration: SearchInputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black.withValues(alpha: 0.8),
),
),
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
),
maxSuggestionsInViewPort: 6,
itemHeight: 50,
onTap: (x) {},
))
SearchField(
onSearchTextChanged: (query) {
final filter = suggestions
.where((element) =>
element.toLowerCase().contains(query.toLowerCase()))
.toList();
return filter
.map((e) => SearchFieldListItem<String>(e,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Text(
Related Skills
node-connect
343.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
92.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
343.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
343.3kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
