diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 4f7c95d1af..c830a82875 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -1241,12 +1241,16 @@ class PopupMenuButtonState extends State> { final RenderBox button = context.findRenderObject()! as RenderBox; final RenderBox overlay = Navigator.of(context).overlay!.context.findRenderObject()! as RenderBox; final PopupMenuPosition popupMenuPosition = widget.position ?? popupMenuTheme.position ?? PopupMenuPosition.over; - final Offset offset; + late Offset offset; switch (popupMenuPosition) { case PopupMenuPosition.over: offset = widget.offset; case PopupMenuPosition.under: - offset = Offset(0.0, button.size.height - (widget.padding.vertical / 2)) + widget.offset; + offset = Offset(0.0, button.size.height) + widget.offset; + if (widget.child == null) { + // Remove the padding of the icon button. + offset -= Offset(0.0, widget.padding.vertical / 2); + } } final RelativeRect position = RelativeRect.fromRect( Rect.fromPoints( diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart index 0772a953d7..a037285242 100644 --- a/packages/flutter/test/material/popup_menu_test.dart +++ b/packages/flutter/test/material/popup_menu_test.dart @@ -3222,6 +3222,44 @@ void main() { await tester.pumpAndSettle(); expect(currentRouteSetting.name, '/'); }); + + testWidgets('Popup menu is positioned under the child', (WidgetTester tester) async { + final Key popupButtonKey = UniqueKey(); + final Key childKey = UniqueKey(); + await tester.pumpWidget( + MaterialApp( + home: Material( + child: Column( + children: [ + PopupMenuButton( + key: popupButtonKey, + position: PopupMenuPosition.under, + itemBuilder: (BuildContext context) { + return >[ + const PopupMenuItem( + child: Text('Example'), + ), + ]; + }, + child: SizedBox( + key: childKey, + height: 50, + width: 50, + ) + ), + ], + ), + ), + ) + ); + + await tester.tap(find.byKey(popupButtonKey)); + await tester.pumpAndSettle(); + + final Offset childBottomLeft = tester.getBottomLeft(find.byKey(childKey)); + final Offset menuTopLeft = tester.getTopLeft(find.bySemanticsLabel('Popup menu')); + expect(childBottomLeft, menuTopLeft); + }); } class TestApp extends StatelessWidget {