Unverified Commit 5805f454 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Fix autocomplete selections (#109185)

parent 7dbe57d4
...@@ -16,6 +16,7 @@ import 'framework.dart'; ...@@ -16,6 +16,7 @@ import 'framework.dart';
import 'inherited_notifier.dart'; import 'inherited_notifier.dart';
import 'overlay.dart'; import 'overlay.dart';
import 'shortcuts.dart'; import 'shortcuts.dart';
import 'tap_region.dart';
/// The type of the [RawAutocomplete] callback which computes the list of /// The type of the [RawAutocomplete] callback which computes the list of
/// optional completions for the widget's field, based on the text the user has /// optional completions for the widget's field, based on the text the user has
...@@ -421,13 +422,15 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>> ...@@ -421,13 +422,15 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
link: _optionsLayerLink, link: _optionsLayerLink,
showWhenUnlinked: false, showWhenUnlinked: false,
targetAnchor: Alignment.bottomLeft, targetAnchor: Alignment.bottomLeft,
child: AutocompleteHighlightedOption( child: TextFieldTapRegion(
highlightIndexNotifier: _highlightedOptionIndex, child: AutocompleteHighlightedOption(
child: Builder( highlightIndexNotifier: _highlightedOptionIndex,
builder: (BuildContext context) { child: Builder(
return widget.optionsViewBuilder(context, _select, _options); builder: (BuildContext context) {
} return widget.optionsViewBuilder(context, _select, _options);
) }
)
),
), ),
); );
}, },
...@@ -527,22 +530,24 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>> ...@@ -527,22 +530,24 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return TextFieldTapRegion(
key: _fieldKey, child: Container(
child: Shortcuts( key: _fieldKey,
shortcuts: _shortcuts, child: Shortcuts(
child: Actions( shortcuts: _shortcuts,
actions: _actionMap, child: Actions(
child: CompositedTransformTarget( actions: _actionMap,
link: _optionsLayerLink, child: CompositedTransformTarget(
child: widget.fieldViewBuilder == null link: _optionsLayerLink,
? const SizedBox.shrink() child: widget.fieldViewBuilder == null
: widget.fieldViewBuilder!( ? const SizedBox.shrink()
context, : widget.fieldViewBuilder!(
_textEditingController, context,
_focusNode, _textEditingController,
_onFieldSubmitted, _focusNode,
), _onFieldSubmitted,
),
),
), ),
), ),
), ),
......
...@@ -129,6 +129,76 @@ void main() { ...@@ -129,6 +129,76 @@ void main() {
expect(lastOptions.elementAt(5), 'northern white rhinoceros'); expect(lastOptions.elementAt(5), 'northern white rhinoceros');
}); });
testWidgets('tapping on an option selects it', (WidgetTester tester) async {
final GlobalKey fieldKey = GlobalKey();
final GlobalKey optionsKey = GlobalKey();
late Iterable<String> lastOptions;
late FocusNode focusNode;
late TextEditingController textEditingController;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: RawAutocomplete<String>(
optionsBuilder: (TextEditingValue textEditingValue) {
return kOptions.where((String option) {
return option.contains(textEditingValue.text.toLowerCase());
});
},
fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
focusNode = fieldFocusNode;
textEditingController = fieldTextEditingController;
return TextField(
key: fieldKey,
focusNode: focusNode,
controller: textEditingController,
);
},
optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<String> onSelected, Iterable<String> options) {
lastOptions = options;
return Material(
elevation: 4.0,
child: ListView.builder(
key: optionsKey,
padding: const EdgeInsets.all(8.0),
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final String option = options.elementAt(index);
return GestureDetector(
onTap: () {
onSelected(option);
},
child: ListTile(
title: Text(option),
),
);
},
),
);
},
),
),
),
);
// The field is always rendered, but the options are not unless needed.
expect(find.byKey(fieldKey), findsOneWidget);
expect(find.byKey(optionsKey), findsNothing);
// Tap on the text field to open the options.
await tester.tap(find.byKey(fieldKey));
await tester.pump();
expect(find.byKey(optionsKey), findsOneWidget);
expect(lastOptions.length, kOptions.length);
await tester.tap(find.text(kOptions[2]));
await tester.pump();
expect(find.byKey(optionsKey), findsNothing);
expect(textEditingController.text, equals(kOptions[2]));
});
testWidgets('can filter and select a list of custom User options', (WidgetTester tester) async { testWidgets('can filter and select a list of custom User options', (WidgetTester tester) async {
final GlobalKey fieldKey = GlobalKey(); final GlobalKey fieldKey = GlobalKey();
final GlobalKey optionsKey = GlobalKey(); final GlobalKey optionsKey = GlobalKey();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment