TypeAheadField<T> class

Flutter TypeAhead

A TypeAhead widget for Flutter, where you can show suggestions to users as they type

Features

  • Shows suggestions in an overlay that floats on top of other widgets
  • Allows you to specify what the suggestions will look like through a builder function
  • Allows you to specify what happens when the user taps a suggestion
  • Accepts all the parameters that traditional TextFields accept, like decoration, custom TextEditingController, text styling, etc.
  • Provides two versions, a normal version and a FormField version that accepts validation, submitting, etc.
  • Provides high customizability; you can customize the suggestion box decoration, the loading bar, the animation, the debounce duration, etc.

Installation

See the installation instructions on pub.

Usage examples

You can import the package with:

import 'package:flutter_typeahead/flutter_typeahead.dart';

and then use it as follows:

Example 1:

TypeAheadField(
  textFieldConfiguration: TextFieldConfiguration(
    autofocus: true,
    style: DefaultTextStyle.of(context).style.copyWith(
      fontStyle: FontStyle.italic
    ),
    decoration: InputDecoration(
      border: OutlineInputBorder()
    )
  ),
  suggestionsCallback: (pattern) async {
    return await BackendService.getSuggestions(pattern);
  },
  itemBuilder: (context, suggestion) {
    return ListTile(
      leading: Icon(Icons.shopping_cart),
      title: Text(suggestion['name']),
      subtitle: Text('\$${suggestion['price']}'),
    );
  },
  onSuggestionSelected: (suggestion) {
    Navigator.of(context).push(MaterialPageRoute(
      builder: (context) => ProductPage(product: suggestion)
    ));
  },
)

In the code above, the textFieldConfiguration property allows us to configure the displayed TextField as we want. In this example, we are configuring the autofocus, style and decoration properties.

The suggestionsCallback is called with the search string that the user types, and is expected to return a List of data either synchronously or asynchronously. In this example, we are calling an asynchronous function called BackendService.getSuggestions which fetches the list of suggestions.

The itemBuilder is called to build a widget for each suggestion. In this example, we build a simple ListTile that shows the name and the price of the item. Please note that you shouldn't provide an onTap callback here. The TypeAhead widget takes care of that.

The onSuggestionSelected is a callback called when the user taps a suggestion. In this example, when the user taps a suggestion, we navigate to a page that shows us the information of the tapped product.

Example 2:

Here's another example, where we use the TypeAheadFormField inside a Form:

final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _typeAheadController = TextEditingController();
String _selectedCity;
...
Form(
  key: this._formKey,
  child: Padding(
    padding: EdgeInsets.all(32.0),
    child: Column(
      children: [
        Text(
          'What is your favorite city?'
        ),
        TypeAheadFormField(
          textFieldConfiguration: TextFieldConfiguration(
            controller: this._typeAheadController,
            decoration: InputDecoration(
              labelText: 'City'
            )
          ),
          suggestionsCallback: (pattern) {
            return CitiesService.getSuggestions(pattern);
          },
          itemBuilder: (context, suggestion) {
            return ListTile(
              title: Text(suggestion),
            );
          },
          transitionBuilder: (context, suggestionsBox, controller) {
            return suggestionsBox;
          },
          onSuggestionSelected: (suggestion) {
            this._typeAheadController.text = suggestion;
          },
          validator: (value) {
            if (value.isEmpty) {
              return 'Please select a city';
            }
          },
          onSaved: (value) => this._selectedCity = value,
        ),
        SizedBox(height: 10.0,),
        RaisedButton(
          child: Text('Submit'),
          onPressed: () {
            if (this._formKey.currentState.validate()) {
              this._formKey.currentState.save();
              Scaffold.of(context).showSnackBar(SnackBar(
                content: Text('Your Favorite City is ${this._selectedCity}')
              ));
            }
          },
        )
      ],
    ),
  ),
)

Here, we assign to the controller property of the textFieldConfiguration a TextEditingController that we call _typeAheadController. We use this controller in the onSuggestionSelected callback to set the value of the TextField to the selected suggestion.

The validator callback can be used like any FormField.validator function. In our example, it checks whether a value has been entered, and displays an error message if not. The onSaved callback is used to save the value of the field to the _selectedCity member variable.

The transitionBuilder allows us to customize the animation of the suggestion box. In this example, we are returning the suggestionsBox immediately, meaning that we don't want any animation.

Customizations

TypeAhead widgets consist of a TextField and a suggestion box that shows as the user types. Both are highly customizable

Customizing the TextField

You can customize the text field using the textFieldConfiguration property. You provide this property with an instance of TextFieldConfiguration, which allows you to configure all the usual properties of TextField, like decoration, style, controller, focusNode, autofocus, enabled, etc.

Customizing the Suggestions Box

TypeAhead provides default configurations for the suggestions box. You can, however, override most of them.

Customizing the loader, the error and the "no items found" message

You can use the loadingBuilder, errorBuilder and noItemsFoundBuilder to customize their corresponding widgets. For example, to show a custom error widget:

errorBuilder: (BuildContext context, Object error) =>
  Text(
    '$error',
    style: TextStyle(
      color: Theme.of(context).errorColor
    )
  )

Customizing the animation

You can customize the suggestion box animation through 3 parameters: the animationDuration, the animationStart, and the transitionBuilder.

The animationDuration specifies how long the animation should take, while the animationStart specified what point (between 0.0 and 1.0) the animation should start from. The transitionBuilder accepts the suggestionsBox and animationController as parameters, and should return a widget that uses the animationController to animate the display of the suggestionsBox. For example:

transitionBuilder: (context, suggestionsBox, animationController) =>
  FadeTransition(
    child: suggestionsBox,
    opacity: CurvedAnimation(
      parent: animationController,
      curve: Curves.fastOutSlowIn
    ),
  )

This uses FadeTransition to fade the suggestionsBox into the view. Note how the animationController was provided as the parent of the animation.

In order to fully remove the animation, transitionBuilder should simply return the suggestionsBox. This callback could also be used to wrap the suggestionsBox with any desired widgets, not necessarily for animation.

Customizing the debounce duration

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.

Customizing the offset of the suggestions box

By default, the suggestions box is displayed 5 pixels below the TextField. You can change this by changing the suggestionsBoxVerticalOffset property.

Customizing the decoration of the suggestions box

You can also customize the decoration of the suggestions box using the suggestionsBoxDecoration property. For example, to remove the elevation of the suggestions box, you can write:

suggestionsBoxDecoration: SuggestionsBoxDecoration(
  elevation: 0.0
)

A FormField implementation of TypeAheadField, that allows the value to be saved, validated, etc.

See also:

Inheritance

Constructors

TypeAheadField({required SuggestionsCallback<T> suggestionsCallback, required ItemBuilder<T> itemBuilder, IndexedWidgetBuilder? itemSeparatorBuilder, LayoutArchitecture? layoutArchitecture, bool intercepting = false, required SuggestionSelectionCallback<T> onSuggestionSelected, TextFieldConfiguration textFieldConfiguration = const TextFieldConfiguration(), SuggestionsBoxDecoration suggestionsBoxDecoration = const SuggestionsBoxDecoration(), Duration debounceDuration = const Duration(milliseconds: 300), SuggestionsBoxController? suggestionsBoxController, ScrollController? scrollController, WidgetBuilder? loadingBuilder, WidgetBuilder? noItemsFoundBuilder, ErrorBuilder? errorBuilder, AnimationTransitionBuilder? transitionBuilder, double animationStart = 0.25, Duration animationDuration = const Duration(milliseconds: 500), bool getImmediateSuggestions = false, double suggestionsBoxVerticalOffset = 5.0, AxisDirection direction = AxisDirection.down, bool hideOnLoading = false, bool hideOnEmpty = false, bool hideOnError = false, bool hideSuggestionsOnKeyboardHide = true, bool keepSuggestionsOnLoading = true, bool keepSuggestionsOnSuggestionSelected = false, bool autoFlipDirection = false, bool autoFlipListDirection = true, double autoFlipMinHeight = 64.0, bool hideKeyboard = false, int minCharsForSuggestions = 0, void onSuggestionsBoxToggle(bool)?, bool hideKeyboardOnDrag = false, bool ignoreAccessibleNavigation = false, Key? key})
Creates a TypeAheadField
const

Properties

animationDuration Duration
The duration that transitionBuilder animation takes.
final
animationStart double
The value at which the transitionBuilder animation starts.
final
autoFlipDirection bool
If set to true, in the case where the suggestions box has less than _SuggestionsBoxController.minOverlaySpace to grow in the desired direction, the direction axis will be temporarily flipped if there's more room available in the opposite direction.
final
autoFlipListDirection bool
If set to false, suggestion list will not be reversed according to the autoFlipDirection property.
final
autoFlipMinHeight double
Minimum height below autoFlipDirection is triggered
final
debounceDuration Duration
The duration to wait after the user stops typing before calling suggestionsCallback
final
direction AxisDirection
Determine the SuggestionBox's direction.
final
errorBuilder ErrorBuilder?
Called when suggestionsCallback throws an exception.
final
getImmediateSuggestions bool
If set to true, suggestions will be fetched immediately when the field is added to the view.
final
hashCode int
The hash code for this object.
no setterinherited
hideKeyboard bool
final
hideKeyboardOnDrag bool
If set to true and if the user scrolls through the suggestion list, hide the keyboard automatically. If set to false, the keyboard remains visible. Throws an exception, if hideKeyboardOnDrag and hideSuggestionsOnKeyboardHide are both set to true as they are mutual exclusive.
final
hideOnEmpty bool
If set to true, nothing will be shown if there are no results. noItemsFoundBuilder will also be ignored.
final
hideOnError bool
If set to true, nothing will be shown if there is an error. errorBuilder will also be ignored.
final
hideOnLoading bool
If set to true, no loading box will be shown while suggestions are being fetched. loadingBuilder will also be ignored.
final
hideSuggestionsOnKeyboardHide bool
If set to false, the suggestions box will stay opened after the keyboard is closed.
final
ignoreAccessibleNavigation bool
Allows a bypass of a problem on Flutter 3.7+ with the accessibility through Overlay that prevents flutter_typeahead to register a click on the list of suggestions properly.
final
intercepting bool
Used to overcome Flutter issue 98507 Most commonly experienced when placing the TypeAheadFormField on a google map in Flutter Web.
final
itemBuilder ItemBuilder<T>
Called for each suggestion returned by suggestionsCallback to build the corresponding widget.
final
itemSeparatorBuilder IndexedWidgetBuilder?
final
keepSuggestionsOnLoading bool
If set to false, the suggestions box will show a circular progress indicator when retrieving suggestions.
final
keepSuggestionsOnSuggestionSelected bool
If set to true, the suggestions box will remain opened even after selecting a suggestion.
final
key Key?
Controls how one widget replaces another widget in the tree.
finalinherited
layoutArchitecture LayoutArchitecture?
By default, we render the suggestions in a ListView, using the itemBuilder to construct each element of the list. Specify your own layoutArchitecture if you want to be responsible for layinng out the widgets using some other system (like a grid).
final
loadingBuilder WidgetBuilder?
Called when waiting for suggestionsCallback to return.
final
minCharsForSuggestions int
The minimum number of characters which must be entered before suggestionsCallback is triggered.
final
noItemsFoundBuilder WidgetBuilder?
Called when suggestionsCallback returns an empty array.
final
onSuggestionsBoxToggle → (void Function(bool)?)
final
onSuggestionSelected SuggestionSelectionCallback<T>
Called when a suggestion is tapped.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
scrollController ScrollController?
used to control the scroll behavior of item-builder list
final
suggestionsBoxController SuggestionsBoxController?
Used to control the _SuggestionsBox. Allows manual control to open, close, toggle, or resize the _SuggestionsBox.
final
suggestionsBoxDecoration SuggestionsBoxDecoration
The decoration of the material sheet that contains the suggestions.
final
suggestionsBoxVerticalOffset double
How far below the text field should the suggestions box be
final
suggestionsCallback SuggestionsCallback<T>
Called with the search pattern to get the search suggestions.
final
textFieldConfiguration TextFieldConfiguration
The configuration of the TextField that the TypeAhead widget displays
final
transitionBuilder AnimationTransitionBuilder?
Called to display animations when suggestionsCallback returns suggestions
final

Methods

createElement() StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() State<TypeAheadField<T>>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a one-line detailed description of the object.
inherited
toStringShort() String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited