@@ -277,8 +277,11 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
277277 late final Map <Type , Action <Intent >> _actionMap;
278278 late final _AutocompleteCallbackAction <AutocompletePreviousOptionIntent > _previousOptionAction;
279279 late final _AutocompleteCallbackAction <AutocompleteNextOptionIntent > _nextOptionAction;
280+ late final _AutocompleteCallbackAction <DismissIntent > _hideOptionsAction;
280281 Iterable <T > _options = Iterable <T >.empty ();
281282 T ? _selection;
283+ bool _userHidOptions = false ;
284+ String _lastFieldText = '' ;
282285 final ValueNotifier <int > _highlightedOptionIndex = ValueNotifier <int >(0 );
283286
284287 static const Map <ShortcutActivator , Intent > _shortcuts = < ShortcutActivator , Intent > {
@@ -291,31 +294,41 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
291294
292295 // True iff the state indicates that the options should be visible.
293296 bool get _shouldShowOptions {
294- return _focusNode.hasFocus && _selection == null && _options.isNotEmpty;
297+ return ! _userHidOptions && _focusNode.hasFocus && _selection == null && _options.isNotEmpty;
295298 }
296299
297300 // Called when _textEditingController changes.
298301 Future <void > _onChangedField () async {
302+ final TextEditingValue value = _textEditingController.value;
299303 final Iterable <T > options = await widget.optionsBuilder (
300- _textEditingController. value,
304+ value,
301305 );
302306 _options = options;
303307 _updateHighlight (_highlightedOptionIndex.value);
304308 if (_selection != null
305- && _textEditingController .text != widget.displayStringForOption (_selection! )) {
309+ && value .text != widget.displayStringForOption (_selection! )) {
306310 _selection = null ;
307311 }
312+
313+ // Make sure the options are no longer hidden if the content of the field
314+ // changes (ignore selection changes).
315+ if (value.text != _lastFieldText) {
316+ _userHidOptions = false ;
317+ _lastFieldText = value.text;
318+ }
308319 _updateOverlay ();
309320 }
310321
311322 // Called when the field's FocusNode changes.
312323 void _onChangedFocus () {
324+ // Options should no longer be hidden when the field is re-focused.
325+ _userHidOptions = ! _focusNode.hasFocus;
313326 _updateOverlay ();
314327 }
315328
316329 // Called from fieldViewBuilder when the user submits the field.
317330 void _onFieldSubmitted () {
318- if (_options.isEmpty) {
331+ if (_options.isEmpty || _userHidOptions ) {
319332 return ;
320333 }
321334 _select (_options.elementAt (_highlightedOptionIndex.value));
@@ -340,25 +353,43 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
340353 }
341354
342355 void _highlightPreviousOption (AutocompletePreviousOptionIntent intent) {
356+ if (_userHidOptions) {
357+ _userHidOptions = false ;
358+ _updateOverlay ();
359+ return ;
360+ }
343361 _updateHighlight (_highlightedOptionIndex.value - 1 );
344362 }
345363
346364 void _highlightNextOption (AutocompleteNextOptionIntent intent) {
365+ if (_userHidOptions) {
366+ _userHidOptions = false ;
367+ _updateOverlay ();
368+ return ;
369+ }
347370 _updateHighlight (_highlightedOptionIndex.value + 1 );
348371 }
349372
373+ void _hideOptions (DismissIntent intent) {
374+ if (! _userHidOptions) {
375+ _userHidOptions = true ;
376+ _updateOverlay ();
377+ }
378+ }
379+
350380 void _setActionsEnabled (bool enabled) {
351381 // The enabled state determines whether the action will consume the
352382 // key shortcut or let it continue on to the underlying text field.
353383 // They should only be enabled when the options are showing so shortcuts
354384 // can be used to navigate them.
355385 _previousOptionAction.enabled = enabled;
356386 _nextOptionAction.enabled = enabled;
387+ _hideOptionsAction.enabled = enabled;
357388 }
358389
359390 // Hide or show the options overlay, if needed.
360391 void _updateOverlay () {
361- _setActionsEnabled (_shouldShowOptions );
392+ _setActionsEnabled (_focusNode.hasFocus && _selection == null && _options.isNotEmpty );
362393 if (_shouldShowOptions) {
363394 _floatingOptions? .remove ();
364395 _floatingOptions = OverlayEntry (
@@ -434,9 +465,11 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
434465 _focusNode.addListener (_onChangedFocus);
435466 _previousOptionAction = _AutocompleteCallbackAction <AutocompletePreviousOptionIntent >(onInvoke: _highlightPreviousOption);
436467 _nextOptionAction = _AutocompleteCallbackAction <AutocompleteNextOptionIntent >(onInvoke: _highlightNextOption);
468+ _hideOptionsAction = _AutocompleteCallbackAction <DismissIntent >(onInvoke: _hideOptions);
437469 _actionMap = < Type , Action <Intent >> {
438470 AutocompletePreviousOptionIntent : _previousOptionAction,
439471 AutocompleteNextOptionIntent : _nextOptionAction,
472+ DismissIntent : _hideOptionsAction,
440473 };
441474 SchedulerBinding .instance.addPostFrameCallback ((Duration _) {
442475 _updateOverlay ();
0 commit comments