mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
Fix DropDownButton with no items resulting in RenderFlex overflow (#26143)
This commit is contained in:
parent
d5fd57cfbd
commit
74ebdacad5
|
@ -557,7 +557,7 @@ class DropdownButton<T> extends StatefulWidget {
|
|||
this.iconSize = 24.0,
|
||||
this.isDense = false,
|
||||
this.isExpanded = false,
|
||||
}) : assert(items == null || value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1),
|
||||
}) : assert(items == null || items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1),
|
||||
assert(elevation != null),
|
||||
assert(iconSize != null),
|
||||
assert(isDense != null),
|
||||
|
@ -770,11 +770,17 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
|
|||
|
||||
// If value is null (then _selectedIndex is null) or if disabled then we
|
||||
// display the hint or nothing at all.
|
||||
final IndexedStack innerItemsWidget = IndexedStack(
|
||||
index: _enabled ? (_selectedIndex ?? hintIndex) : hintIndex,
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
children: items,
|
||||
);
|
||||
final int index = _enabled ? (_selectedIndex ?? hintIndex) : hintIndex;
|
||||
Widget innerItemsWidget;
|
||||
if (items.isEmpty) {
|
||||
innerItemsWidget = Container();
|
||||
} else {
|
||||
innerItemsWidget = IndexedStack(
|
||||
index: index,
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
children: items,
|
||||
);
|
||||
}
|
||||
|
||||
Widget result = DefaultTextStyle(
|
||||
style: _textStyle,
|
||||
|
|
|
@ -374,7 +374,7 @@ void main() {
|
|||
Widget build() => buildFrame(buttonKey: buttonKey, value: value, textDirection: textDirection, onChanged: onChanged);
|
||||
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBox.attached);
|
||||
final Offset buttonOriginBeforeTap = buttonBox.localToGlobal(Offset.zero);
|
||||
|
||||
|
@ -388,7 +388,7 @@ void main() {
|
|||
// The selected dropdown item is both in menu we just popped up, and in
|
||||
// the IndexedStack contained by the dropdown button. Both of them should
|
||||
// have the same origin and height as the dropdown button.
|
||||
final List<RenderObject> itemBoxes = tester.renderObjectList(find.byKey(const ValueKey<String>('two'))).toList();
|
||||
final List<RenderObject> itemBoxes = tester.renderObjectList<RenderBox>(find.byKey(const ValueKey<String>('two'))).toList();
|
||||
expect(itemBoxes.length, equals(2));
|
||||
for (RenderBox itemBox in itemBoxes) {
|
||||
assert(itemBox.attached);
|
||||
|
@ -419,10 +419,10 @@ void main() {
|
|||
Widget build() => buildFrame(buttonKey: buttonKey, value: 'two', isExpanded: true, onChanged: onChanged);
|
||||
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBox.attached);
|
||||
|
||||
final RenderBox arrowIcon = tester.renderObject(find.byIcon(Icons.arrow_drop_down));
|
||||
final RenderBox arrowIcon = tester.renderObject<RenderBox>(find.byIcon(Icons.arrow_drop_down));
|
||||
assert(arrowIcon.attached);
|
||||
|
||||
// Arrow icon should be aligned with far right of button when expanded
|
||||
|
@ -437,7 +437,7 @@ void main() {
|
|||
Widget build() => buildFrame(buttonKey: buttonKey, value: value, isDense: true, onChanged: onChanged);
|
||||
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBox.attached);
|
||||
|
||||
await tester.tap(find.text('two'));
|
||||
|
@ -504,7 +504,7 @@ void main() {
|
|||
items: List<String>.generate(/*length=*/ 100, (int index) => index.toString()),
|
||||
onChanged: onChanged,
|
||||
));
|
||||
final RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
await tester.tap(find.byKey(buttonKey));
|
||||
await tester.pumpAndSettle(); // finish the menu animation
|
||||
|
||||
|
@ -519,7 +519,6 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
|
||||
testWidgets('Size of DropdownButton with null value', (WidgetTester tester) async {
|
||||
final Key buttonKey = UniqueKey();
|
||||
String value;
|
||||
|
@ -527,13 +526,12 @@ void main() {
|
|||
Widget build() => buildFrame(buttonKey: buttonKey, value: value, onChanged: onChanged);
|
||||
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBoxNullValue = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBoxNullValue = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBoxNullValue.attached);
|
||||
|
||||
|
||||
value = 'three';
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBox.attached);
|
||||
|
||||
// A Dropdown button with a null value should be the same size as a
|
||||
|
@ -542,6 +540,33 @@ void main() {
|
|||
expect(buttonBox.size, equals(buttonBoxNullValue.size));
|
||||
});
|
||||
|
||||
testWidgets('Size of DropdownButton with no items', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/26419
|
||||
final Key buttonKey = UniqueKey();
|
||||
List<String> items;
|
||||
|
||||
Widget build() => buildFrame(buttonKey: buttonKey, items: items, onChanged: onChanged);
|
||||
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBoxNullItems = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBoxNullItems.attached);
|
||||
|
||||
items = <String>[];
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBoxEmptyItems = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBoxEmptyItems.attached);
|
||||
|
||||
items = <String>['one', 'two', 'three', 'four'];
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBox.attached);
|
||||
|
||||
// A Dropdown button with a null value should be the same size as a
|
||||
// one with a non-null value.
|
||||
expect(buttonBox.localToGlobal(Offset.zero), equals(buttonBoxNullItems.localToGlobal(Offset.zero)));
|
||||
expect(buttonBox.size, equals(buttonBoxNullItems.size));
|
||||
});
|
||||
|
||||
testWidgets('Layout of a DropdownButton with null value', (WidgetTester tester) async {
|
||||
final Key buttonKey = UniqueKey();
|
||||
String value;
|
||||
|
@ -553,7 +578,7 @@ void main() {
|
|||
Widget build() => buildFrame(buttonKey: buttonKey, value: value, onChanged: onChanged);
|
||||
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBox.attached);
|
||||
|
||||
// Show the menu.
|
||||
|
@ -579,13 +604,12 @@ void main() {
|
|||
|
||||
await tester.pumpWidget(build());
|
||||
expect(find.text('onetwothree'), findsOneWidget);
|
||||
final RenderBox buttonBoxHintValue = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBoxHintValue = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBoxHintValue.attached);
|
||||
|
||||
|
||||
value = 'three';
|
||||
await tester.pumpWidget(build());
|
||||
final RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox buttonBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
assert(buttonBox.attached);
|
||||
|
||||
// A Dropdown button with a null value and a hint should be the same size as a
|
||||
|
@ -714,7 +738,6 @@ void main() {
|
|||
expect(find.byType(ListView, skipOffstage: false), findsNothing);
|
||||
});
|
||||
|
||||
|
||||
testWidgets('Semantics Tree contains only selected element', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = SemanticsTester(tester);
|
||||
await tester.pumpWidget(buildFrame(items: menuItems, onChanged: onChanged));
|
||||
|
@ -853,14 +876,14 @@ void main() {
|
|||
await tester.pumpWidget(build(items: menuItems, onChanged: null));
|
||||
expect(find.text('enabled'), findsNothing);
|
||||
expect(find.text('disabled'), findsOneWidget);
|
||||
final RenderBox disabledHintBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox disabledHintBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
|
||||
// A Dropdown button with a disabled hint should be the same size as a
|
||||
// one with a regular enabled hint.
|
||||
await tester.pumpWidget(build(items: menuItems, onChanged: onChanged));
|
||||
expect(find.text('disabled'), findsNothing);
|
||||
expect(find.text('enabled'), findsOneWidget);
|
||||
final RenderBox enabledHintBox = tester.renderObject(find.byKey(buttonKey));
|
||||
final RenderBox enabledHintBox = tester.renderObject<RenderBox>(find.byKey(buttonKey));
|
||||
expect(enabledHintBox.localToGlobal(Offset.zero), equals(disabledHintBox.localToGlobal(Offset.zero)));
|
||||
expect(enabledHintBox.size, equals(disabledHintBox.size));
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue