Multi Trigger Autocomplete
A flutter widget to add trigger based autocomplete functionality to your app.
Show some ❤️ and star the repo to support the project
Installation
Add the following to your pubspec.yaml
and replace [version]
with the latest version:
dependencies:
multi_trigger_autocomplete: ^[version]
Usage
To use this package you must first wrap your top most widget with Portal as this package uses flutter_portal to show the options view.
(Credits to: Remi Rousselet)
Portal
, is the equivalent of Overlay.This widget will need to be inserted above the widget that needs to render under your overlays.
If you want to display your overlays on the top of everything, a good place to insert that
Portal
is aboveMaterialApp
:Portal( child: MaterialApp( ... ) );
(works for
CupertinoApp
too)This way
Portal
will render above everything. But you could place it somewhere else to change the clip behavior.
Import the package:
import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart';
Use the widget:
MultiTriggerAutocomplete(
optionsAlignment: OptionsAlignment.topStart,
autocompleteTriggers: [
// Add the triggers you want to use for autocomplete
AutocompleteTrigger(
trigger: '@',
optionsViewBuilder: (context, autocompleteQuery, controller) {
return MentionAutocompleteOptions(
query: autocompleteQuery.query,
onMentionUserTap: (user) {
final autocomplete = MultiTriggerAutocomplete.of(context);
return autocomplete.acceptAutocompleteOption(user.id);
},
);
},
),
AutocompleteTrigger(
trigger: '#',
optionsViewBuilder: (context, autocompleteQuery, controller) {
return HashtagAutocompleteOptions(
query: autocompleteQuery.query,
onHashtagTap: (hashtag) {
final autocomplete = MultiTriggerAutocomplete.of(context);
return autocomplete
.acceptAutocompleteOption(hashtag.name);
},
);
},
),
AutocompleteTrigger(
trigger: ':',
optionsViewBuilder: (context, autocompleteQuery, controller) {
return EmojiAutocompleteOptions(
query: autocompleteQuery.query,
onEmojiTap: (emoji) {
final autocomplete = MultiTriggerAutocomplete.of(context);
return autocomplete.acceptAutocompleteOption(
emoji.char,
// Passing false as we don't want the trigger [:] to
// get prefixed to the option in case of emoji.
keepTrigger: false,
);
},
);
},
),
],
// Add the text field widget you want to use for autocomplete
fieldViewBuilder: (context, controller, focusNode) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ChatMessageTextField(
focusNode: focusNode,
controller: controller,
),
);
},
),
Demo
Mention Autocomplete | Hashtag Autocomplete | Emoji Autocomplete |
---|---|---|
Customization
MultiTriggerAutocomplete
MultiTriggerAutocomplete(
// Defines the autocomplete trigger that will be used to match the
// text.
autocompleteTriggers: autocompleteTriggers,
// Defines the alignment of the options view relative to the
// fieldView.
//
// By default, the options view is aligned to the bottom of the
// fieldView.
optionsAlignment: OptionsAlignment.topStart,
// Defines the width to make the options as a multiple of the width
// of the fieldView.
//
// Setting this to 1 makes the options view width matches the width
// of the fieldView.
//
// Use null to remove this constraint.
optionsWidthFactor: 1.0,
// Defines the duration of the debounce period for the
// [TextEditingController].
//
// This is the time between the last character typed and the matching
// is performed.
debounceDuration: const Duration(milliseconds: 350),
// Defines the initial value to set in the internal
// [TextEditingController].
//
// This value will be ignored if [TextEditingController] is provided.
initialValue: const TextEditingValue(text: 'Hello'),
// Defines the [TextEditingController] that will be used for the
// fieldView.
//
// If this parameter is provided, then [focusNode] must also be
// provided.
textEditingController: TextEditingController(text: 'Hello'),
// Defines the [FocusNode] that will be used for the fieldView.
//
// If this parameter is provided, then [textEditingController] must
// also be provided.
focusNode: FocusNode(),
// Defines the fieldView that will be used to input the text.
//
// By default, a [TextFormField] is used.
fieldViewBuilder: (context, controller, focusNode) {
return TextField(
controller: controller,
focusNode: focusNode,
);
},
),
AutocompleteTrigger
AutocompleteTrigger(
// The trigger string/character that will be used to trigger the
// autocomplete.
trigger: '@',
// If true, the [trigger] should only be recognised at
// the start of the input text.
//
// valid example: "@luke hello"
// invalid example: "Hello @luke"
triggerOnlyAtStart: false,
// If true, the [trigger] should only be recognised after
// a space.
//
// valid example: "@luke", "Hello @luke"
// invalid example: "Hello@luke"
triggerOnlyAfterSpace: true,
// A minimum number of characters can be provided to only show
// suggestions after the user has input enough characters.
//
// example:
// "Hello @l" -> Shows zero suggestions.
// "Hello @lu" -> Shows suggestions for @lu.
minimumRequiredCharacters: 2,
// The options view builder is used to build the options view
// that will be shown when the [trigger] is detected.
optionsViewBuilder: (context, autocompleteQuery, controller) {
return MentionAutocompleteOptions(
query: autocompleteQuery.query,
onMentionUserTap: (user) {
// Accept the autocomplete option.
final autocomplete = MultiTriggerAutocomplete.of(context);
return autocomplete.acceptAutocompleteOption(user.id);
},
);
},
)