A TypeAhead (autocomplete) widget for Flutter, where you can show suggestions to users as they type
For installation, see installation instructions.
You can import the package with:
import 'package:flutter_typeahead/flutter_typeahead.dart';
The package comes in both Material and Cupertino widget flavors. All parameters identical, the only changes are the visual defaults.
TypeAheadField<City>(
suggestionsCallback: (search) => CityService.of(context).find(search),
builder: (context, controller, focusNode) {
return TextField(
controller: controller,
focusNode: focusNode,
autofocus: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'City',
)
);
},
itemBuilder: (context, city) {
return ListTile(
title: Text(city.name),
subtitle: Text(city.country),
);
},
onSelected: (city) {
Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => CityPage(city: city),
),
);
},
)
By default, TypeAhead uses a ListView
to render the items created by itemBuilder
.
You may specify a custom layout via the listBuilder
property.
For example, to use a GridView
:
TypeAheadField(
// ...
listBuilder: (context, children) => GridView.count(
controller: scrollContoller,
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
shrinkWrap: true,
reverse: SuggestionsController.of<City>(context).effectiveDirection ==
VerticalDirection.up,
children: children,
),
);
Note: To inherit the correct ScrollController
, please do not set primary
to false
.
The suggestions box will automatically provide an ambient PrimaryScrollController
.
The TypeAheadField
will use a simple default TextField
builder, if none is provided.
To customize your TextField
, you can use the builder
property.
You may also use a TextFormField
or any other widget that connects to a TextEditingController
and FocusNode
.
TypeAheadField(
// ...
builder: (context, controller, focusNode) {
return TextField(
controller: controller,
focusNode: focusNode,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
labelText: 'Password',
),
);
},
);
It is crucial that you use the provided controller
and focusNode
properties,
as they are required for the suggestions box to function.
The TypeAheadField
will use a simple default decoration builder.
To customize the suggestions box, you can create your own decoration builder.
You may also specify offsets and constraints to position the suggestions box.
TypeAheadField(
// ...
decorationBuilder: (context, child) {
return Material(
type: MaterialType.card,
elevation: 4,
borderRadius: BorderRadius.circular(8),
child: child,
);
},
offset: Offset(0, 12),
constraints: BoxConstraints(maxHeight: 500),
);
You can use the loadingBuilder
, errorBuilder
and emptyBuilder
to
customize their corresponding widgets.
For example:
TypeAheadField(
// ...
loadingBuilder: (context) => const Text('Loading...'),
errorBuilder: (context, error) => const Text('Error!'),
emptyBuilder: (context) => const Text('No items found!'),
);
By default, the suggestions box will maintain the old suggestions while new
suggestions are being retrieved. To show a circular progress indicator
during retrieval instead, set keepSuggestionsOnLoading
to false.
You may want to hide the suggestions box when it is in certain states. You can do so with the following parameters:
hideOnLoading
: Hide the suggestions box while suggestions are being retrieved. This ignores the loadingBuilder
.hideOnEmpty
: Hide the suggestions box when there are no suggestions. This ignores the emptyBuilder
.hideOnError
: Hide the suggestions box when there is an error retrieving suggestions. This ignores the errorBuilder
.hideOnSelect
: Hide the suggestions box when a suggestion is selected. True
by default.hideOnUnfocus
: Hide the suggestions box when the TextField
loses focus. True
by default.hideWithKeyboard
: Hide the suggestions box when the keyboard is hidden. True
by default.You can also very generally hide the suggestions box by returning null
from the suggestionsCallback
.
This is different from returning an empty list, which will show the empty widget.
Animation duration can be customized using the animationDuration
parameter.
You may also specify a custom animation using the transitionBuilder
parameter.
For example:
TypeAheadField(
// ...
transitionBuilder: (context, animation, child) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn
),
child: child,
),
},
);
To disable animatons, return the child
directly.
The suggestions box does not fire for each character the user types. Instead,
we wait until the user is idle for a duration of time, and then call the
suggestionsCallback
. The duration defaults to 300 milliseconds``, but can be configured using the
debounceDuration` parameter.
By default, the list grows towards the bottom. However, you can use the direction
to specify either VerticalDirection.down
or VerticalDirection.up
.
The suggestions list will automatically reverse in case it is flipped.
To turn off this behavior, set autoFlipDirection
to false
.
You may manually control many aspects of the suggestions box by using the SuggestionsController
class.
It grants access to the following:
When building a widget inside of the suggestions box, you can access the controller via SuggestionsController.of(context)
.
Focus plays an important role in the suggestions box. It is used to determine when to show and hide the suggestions box. However, in certain situations you may want to control the suggestions box independently of the focus.
Options to do so are as follows:
On the TypeAheadField
:
showOnFocus
(default: true
): Show the suggestions box when the TextField
gains focus.hideOnUnfocus
(default: true
): Hide the suggestions box when the TextField
loses focus.On the SuggestionsController
:
open(gainFocus: false)
: Show the suggestions box without focusing it.close(retainFocus: true)
: Hide the suggestions box without unfocusing it.To create your own version of the TypeAhead widget, that is neither Material nor Cupertino, you can use the RawTypeAheadField
widget.
You must then specify the following parameters:
builder
(to build the TextField
)loadingBuilder
(to build the loading widget)errorBuilder
(to build the error widget)emptyBuilder
(to build the empty widget)itemBuilder
(to build the suggestions)As well as all the usual parameters, such as suggestionsCallback
, onSelected
, etc.
The decorationBuilder
can be used to inject required wrappers like Material
or DefaultTextStyle
.
For more information, see the source code of the TypeAheadField
widget.
You have most likely forgotten to pass the controller and focus node to the TextField
in the builder
property.
This is required for the suggestions box to function. Here is an example:
TypeAheadField(
// ...
controller: myTextEditingController, // your custom controller, or null
builder: (context, controller, focusNode) {
return TextField(
controller: controller, // note how the controller is passed
focusNode: focusNode,
// ...
);
},
);
The TypeAhead field caches the suggestions to avoid unnecessary calls to the suggestionsCallback
.
If you want to force the suggestions to update, you can use the SuggestionsController
to force a refresh.
mySuggestionsController.refresh();
Since version 5.x, the package is based on Dart 3 (null-safety enforced). To use this package, please upgrade your Flutter SDK.
Additionally, various changes have been made to the API surface to make the package more flexible and customizable. The following changes have been made:
SuggestionsBoxDecoration
has been removed. You can now directly wrap the SuggestionsBox
with any widget you wish via the decorationBuilder
property.TextFieldConfiguration
has been removed. You can now directly build your own custom TextField
via the builder
property.
Note that you must use the provided controller
and focusNode
properties, as they are required for the suggestions box to function.SuggestionsBoxController
has been renamed to SuggestionsController
.CupertinoSuggestionsBoxController
has been merged into SuggestionsController
.SuggestionsController
now holds the full state of the suggestions box, meaning suggestions, loading and error state. It will also send notifications when state changes occur.SuggestionsController
now offers streams for when a suggestion is selected.SuggestionsBox
should now automatically resize in all situations. Manual resize calls are no longer required.TypeAheadFormField
has been removed. You can use the builder
property to build your own TextFormField
.suggestionsBoxController
-> suggestionsController
layoutArchitecture
-> listBuilder
noItemsFoundBuilder
-> emptyBuilder
onSuggestionSelected
-> onSelected
suggestionsBoxVerticalOffset
-> offset
(now also includes horizontal offset)hideSuggestionsOnKeyboardHide
-> hideWithKeyboard
keepSuggestionsOnSuggestionSelected
-> hideOnSelect
(inverted)keepSuggestionsOnLoading
-> retainOnLoading
intercepting
: This is now always true, since it doesnt interfere on mobile platforms and generally has no downsides.onSuggestionsBoxToggle
: You can subscribe to the SuggestionsController
to get notified when the suggestions box is toggled.ignoreAccessibleNavigation
: The new Overlay
code no longer requires to act differently when accessibility is enabled.minCharsForSuggestions
: You can return null
from suggestionsCallback
instead.animationStart
: You can use the animation in the builder and map it to customise this.autoFlipListDirection
: This is now always true. You can use the list builder to disable this behavior.getImmediateSuggestions
: You can use the debounceDuration
to achieve the same effect.Since version 3.x, the package is based on Dart 2.12 (null-safety). Flutter now also features the inbuilt Autocomplete widget, which has similar behavior to this package.
Visit the API Documentation.
AbdulRahman AlHamali | S McDowall | Kenneth Liang | clragon |
This project is the result of the collective effort of contributors who participated effectively by submitting pull requests, reporting issues, and answering questions.
Thank you for your proactiveness, and we hope flutter_typeahead
made your lifes at least a little easier!
If you would like to contribute, please read the Contribution Guidelines.