Unverified Commit 8d866d9c authored by xubaolin's avatar xubaolin Committed by GitHub

Fix DropdownButton crash when viewport size is too small for the entirety of...

Fix DropdownButton crash when viewport size is too small for the entirety of the menu's height (#76764)
parent fc77610d
......@@ -65,12 +65,12 @@ class _DropdownMenuPainter extends CustomPainter {
void paint(Canvas canvas, Size size) {
final double selectedItemOffset = getSelectedItemOffset();
final Tween<double> top = Tween<double>(
begin: selectedItemOffset.clamp(0.0, size.height - _kMenuItemHeight),
begin: selectedItemOffset.clamp(0.0, math.max(size.height - _kMenuItemHeight, 0.0)),
end: 0.0,
);
final Tween<double> bottom = Tween<double>(
begin: (top.begin! + _kMenuItemHeight).clamp(_kMenuItemHeight, size.height),
begin: (top.begin! + _kMenuItemHeight).clamp(math.min(_kMenuItemHeight, size.height), size.height),
end: size.height,
);
......
......@@ -3008,4 +3008,61 @@ void main() {
expect(scrollController.position.maxScrollExtent > 0, isTrue);
expect(find.byType(Scrollbar), paints..rect());
});
// Regression test for https://github.com/flutter/flutter/issues/76614
testWidgets('Do not crash if used in very short screen', (WidgetTester tester) async {
// The default item height is 48.0 pixels and needs two items padding since
// the menu requires empty space surrounding the menu. Finally, the constraint height
// is 47.0 pixels for the menu rendering.
tester.binding.window.physicalSizeTestValue = const Size(800.0, 48.0 * 3 - 1.0);
tester.binding.window.devicePixelRatioTestValue = 1;
addTearDown(tester.binding.window.clearPhysicalSizeTestValue);
addTearDown(tester.binding.window.clearDevicePixelRatioTestValue);
const String value = 'foo';
final UniqueKey itemKey = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: DropdownButton<String>(
value: value,
items: <DropdownMenuItem<String>>[
DropdownMenuItem<String>(
key: itemKey,
value: value,
child: const Text(value),
),
],
onChanged: (_) { },
),
),
),
),
);
await tester.tap(find.text(value));
await tester.pumpAndSettle();
final List<RenderBox> itemBoxes = tester.renderObjectList<RenderBox>(find.byKey(itemKey)).toList();
expect(itemBoxes[0].localToGlobal(Offset.zero).dx, 364.0);
expect(itemBoxes[0].localToGlobal(Offset.zero).dy, 47.5);
expect(itemBoxes[1].localToGlobal(Offset.zero).dx, 364.0);
expect(itemBoxes[1].localToGlobal(Offset.zero).dy, 47.5);
expect(
find.ancestor(
of: find.text(value).last,
matching: find.byType(CustomPaint),
).at(2),
paints
..save()
..rrect()
..rrect()
..rrect()
// The height of menu is 47.0.
..rrect(rrect: const RRect.fromLTRBXY(0.0, 0.0, 112.0, 47.0, 2.0, 2.0), color: Colors.grey[50], hasMaskFilter: false)
);
});
}
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