Unverified Commit 238bc4bf authored by Mahesh Jamdade's avatar Mahesh Jamdade Committed by GitHub

Fix autocomplete options height (#80187)

parent 1e35f4c0
......@@ -166,6 +166,7 @@ class Autocomplete<T extends Object> extends StatelessWidget {
this.displayStringForOption = RawAutocomplete.defaultStringForOption,
this.fieldViewBuilder = _defaultFieldViewBuilder,
this.onSelected,
this.optionsMaxHeight = 200.0,
this.optionsViewBuilder,
this.initialValue,
}) : assert(displayStringForOption != null),
......@@ -193,6 +194,14 @@ class Autocomplete<T extends Object> extends StatelessWidget {
/// default.
final AutocompleteOptionsViewBuilder<T>? optionsViewBuilder;
/// The maximum height used for the default Material options list widget.
///
/// When [optionsViewBuilder] is `null`, this property sets the maximum height
/// that the options widget can occupy.
///
/// The default value is set to 200.
final double optionsMaxHeight;
/// {@macro flutter.widgets.RawAutocomplete.initialValue}
final TextEditingValue? initialValue;
......@@ -216,6 +225,7 @@ class Autocomplete<T extends Object> extends StatelessWidget {
displayStringForOption: displayStringForOption,
onSelected: onSelected,
options: options,
maxOptionsHeight: optionsMaxHeight,
);
},
onSelected: onSelected,
......@@ -257,6 +267,7 @@ class _AutocompleteOptions<T extends Object> extends StatelessWidget {
required this.displayStringForOption,
required this.onSelected,
required this.options,
required this.maxOptionsHeight,
}) : super(key: key);
final AutocompleteOptionToString<T> displayStringForOption;
......@@ -264,6 +275,7 @@ class _AutocompleteOptions<T extends Object> extends StatelessWidget {
final AutocompleteOnSelected<T> onSelected;
final Iterable<T> options;
final double maxOptionsHeight;
@override
Widget build(BuildContext context) {
......@@ -271,10 +283,11 @@ class _AutocompleteOptions<T extends Object> extends StatelessWidget {
alignment: Alignment.topLeft,
child: Material(
elevation: 4.0,
child: SizedBox(
height: 200.0,
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: maxOptionsHeight),
child: ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final T option = options.elementAt(index);
......
......@@ -254,6 +254,104 @@ void main() {
expect(find.byKey(optionsKey), findsOneWidget);
});
testWidgets('the default Autocomplete options widget has a maximum height of 200', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(home: Scaffold(
body: Autocomplete<String>(
optionsBuilder: (TextEditingValue textEditingValue) {
return kOptions.where((String option) {
return option.contains(textEditingValue.text.toLowerCase());
});
},
),
)));
final Finder listFinder = find.byType(ListView);
final Finder inputFinder = find.byType(TextFormField);
await tester.tap(inputFinder);
await tester.enterText(inputFinder, '');
await tester.pump();
final Size baseSize = tester.getSize(listFinder);
final double resultingHeight = baseSize.height;
expect(resultingHeight, equals(200));
});
testWidgets('the options height restricts to max desired height', (WidgetTester tester) async {
const double desiredHeight = 150.0;
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Autocomplete<String>(
optionsMaxHeight: desiredHeight,
optionsBuilder: (TextEditingValue textEditingValue) {
return kOptions.where((String option) {
return option.contains(textEditingValue.text.toLowerCase());
});
},
),
)));
/// entering "a" returns 9 items from kOptions so basically the
/// height of 9 options would be beyond `desiredHeight=150`,
/// so height gets restricted to desiredHeight.
final Finder listFinder = find.byType(ListView);
final Finder inputFinder = find.byType(TextFormField);
await tester.tap(inputFinder);
await tester.enterText(inputFinder, 'a');
await tester.pump();
final Size baseSize = tester.getSize(listFinder);
final double resultingHeight = baseSize.height;
/// expected desired Height =150.0
expect(resultingHeight, equals(desiredHeight));
});
testWidgets('The height of options shrinks to height of resulting items, if less than maxHeight', (WidgetTester tester) async {
// Returns a Future with the height of the default [Autocomplete] options widget
// after the provided text had been entered into the [Autocomplete] field.
Future<double> _getDefaultOptionsHeight(
WidgetTester tester, String enteredText) async {
final Finder listFinder = find.byType(ListView);
final Finder inputFinder = find.byType(TextFormField);
final TextFormField field = inputFinder.evaluate().first.widget as TextFormField;
field.controller!.clear();
await tester.tap(inputFinder);
await tester.enterText(inputFinder, enteredText);
await tester.pump();
final Size baseSize = tester.getSize(listFinder);
return baseSize.height;
}
const double maxOptionsHeight = 250.0;
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Autocomplete<String>(
optionsMaxHeight: maxOptionsHeight,
optionsBuilder: (TextEditingValue textEditingValue) {
return kOptions.where((String option) {
return option.contains(textEditingValue.text.toLowerCase());
});
},
),
)));
final Finder listFinder = find.byType(ListView);
expect(listFinder, findsNothing);
/// entering `a` returns 9 items(height > `maxOptionsheight`) from the kOptions
/// so height gets restricted to `maxOptionsheight =250`
final double nineItemsHeight = await _getDefaultOptionsHeight(tester, 'a');
expect(nineItemsHeight, equals(maxOptionsHeight));
/// returns 2 Items (height < `maxOptionsHeight`)
/// so options height shrinks to 2 Items combined height
final double twoItemsHeight = await _getDefaultOptionsHeight(tester, 'el');
expect(twoItemsHeight, lessThan(maxOptionsHeight));
/// returns 1 item (height < `maxOptionsHeight`) from `kOptions`
/// so options height shrinks to 1 items height
final double oneItemsHeight = await _getDefaultOptionsHeight(tester, 'elep');
expect(oneItemsHeight, lessThan(twoItemsHeight));
});
testWidgets('initialValue sets initial text field value', (WidgetTester tester) async {
late String lastSelection;
await tester.pumpWidget(
......
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