Skip to content

Commit 43d22ae

Browse files
authored
Re-add the removed MediaQuery.removePadding of PopupMenuButton (#82986)
1 parent 669a815 commit 43d22ae

2 files changed

Lines changed: 108 additions & 34 deletions

File tree

packages/flutter/lib/src/material/popup_menu.dart

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -624,8 +624,7 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
624624
this.itemSizes,
625625
this.selectedItemIndex,
626626
this.textDirection,
627-
this.topPadding,
628-
this.bottomPadding,
627+
this.padding,
629628
);
630629

631630
// Rectangle of underlying button, relative to the overlay's dimensions.
@@ -642,11 +641,8 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
642641
// Whether to prefer going to the left or to the right.
643642
final TextDirection textDirection;
644643

645-
// Top padding of unsafe area.
646-
final double topPadding;
647-
648-
// Bottom padding of unsafe area.
649-
final double bottomPadding;
644+
// The padding of unsafe area.
645+
EdgeInsets padding;
650646

651647
// We put the child wherever position specifies, so long as it will fit within
652648
// the specified parent size padded (inset) by 8. If necessary, we adjust the
@@ -657,7 +653,7 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
657653
// The menu can be at most the size of the overlay minus 8.0 pixels in each
658654
// direction.
659655
return BoxConstraints.loose(constraints.biggest).deflate(
660-
const EdgeInsets.all(_kMenuScreenPadding) + EdgeInsets.only(top: topPadding, bottom: bottomPadding),
656+
const EdgeInsets.all(_kMenuScreenPadding) + padding,
661657
);
662658
}
663659

@@ -701,14 +697,15 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
701697

702698
// Avoid going outside an area defined as the rectangle 8.0 pixels from the
703699
// edge of the screen in every direction.
704-
if (x < _kMenuScreenPadding)
705-
x = _kMenuScreenPadding;
706-
else if (x + childSize.width > size.width - _kMenuScreenPadding)
707-
x = size.width - childSize.width - _kMenuScreenPadding;
708-
if (y < _kMenuScreenPadding + topPadding)
709-
y = _kMenuScreenPadding + topPadding;
710-
else if (y + childSize.height > size.height - _kMenuScreenPadding - bottomPadding)
711-
y = size.height - bottomPadding - _kMenuScreenPadding - childSize.height ;
700+
if (x < _kMenuScreenPadding + padding.left)
701+
x = _kMenuScreenPadding + padding.left;
702+
else if (x + childSize.width > size.width - _kMenuScreenPadding - padding.right)
703+
x = size.width - childSize.width - _kMenuScreenPadding - padding.right ;
704+
if (y < _kMenuScreenPadding + padding.top)
705+
y = _kMenuScreenPadding + padding.top;
706+
else if (y + childSize.height > size.height - _kMenuScreenPadding - padding.bottom)
707+
y = size.height - padding.bottom - _kMenuScreenPadding - childSize.height ;
708+
712709
return Offset(x, y);
713710
}
714711

@@ -723,8 +720,7 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
723720
|| selectedItemIndex != oldDelegate.selectedItemIndex
724721
|| textDirection != oldDelegate.textDirection
725722
|| !listEquals(itemSizes, oldDelegate.itemSizes)
726-
|| topPadding != oldDelegate.topPadding
727-
|| bottomPadding != oldDelegate.bottomPadding;
723+
|| padding != oldDelegate.padding;
728724
}
729725
}
730726

@@ -784,22 +780,27 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
784780
}
785781

786782
final Widget menu = _PopupMenu<T>(route: this, semanticLabel: semanticLabel);
787-
788-
return Builder(
789-
builder: (BuildContext context) {
790-
final MediaQueryData mediaQuery = MediaQuery.of(context);
791-
return CustomSingleChildLayout(
792-
delegate: _PopupMenuRouteLayout(
793-
position,
794-
itemSizes,
795-
selectedItemIndex,
796-
Directionality.of(context),
797-
mediaQuery.padding.top,
798-
mediaQuery.padding.bottom,
799-
),
800-
child: capturedThemes.wrap(menu),
801-
);
802-
},
783+
final MediaQueryData mediaQuery = MediaQuery.of(context);
784+
return MediaQuery.removePadding(
785+
context: context,
786+
removeTop: true,
787+
removeBottom: true,
788+
removeLeft: true,
789+
removeRight: true,
790+
child: Builder(
791+
builder: (BuildContext context) {
792+
return CustomSingleChildLayout(
793+
delegate: _PopupMenuRouteLayout(
794+
position,
795+
itemSizes,
796+
selectedItemIndex,
797+
Directionality.of(context),
798+
mediaQuery.padding,
799+
),
800+
child: capturedThemes.wrap(menu),
801+
);
802+
},
803+
),
803804
);
804805
}
805806
}

packages/flutter/test/material/popup_menu_test.dart

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,6 +2191,79 @@ void main() {
21912191
expect(popupMenu, Offset(button.dx - 8.0, button.dy + 8.0));
21922192
});
21932193

2194+
// Regression test for https://github.com/flutter/flutter/issues/82874
2195+
testWidgets('PopupMenu position test when have unsafe area - left/right padding', (WidgetTester tester) async {
2196+
final GlobalKey buttonKey = GlobalKey();
2197+
const EdgeInsets padding = EdgeInsets.only(left: 300.0, top: 32.0, right: 310.0, bottom: 64.0);
2198+
EdgeInsets? mediaQueryPadding;
2199+
2200+
Widget buildFrame(double width, double height) {
2201+
return MaterialApp(
2202+
builder: (BuildContext context, Widget? child) {
2203+
return MediaQuery(
2204+
data: const MediaQueryData(
2205+
padding: padding,
2206+
),
2207+
child: child!,
2208+
);
2209+
},
2210+
home: Scaffold(
2211+
appBar: AppBar(
2212+
title: const Text('PopupMenu Test'),
2213+
actions: <Widget>[PopupMenuButton<int>(
2214+
child: SizedBox(
2215+
key: buttonKey,
2216+
height: height,
2217+
width: width,
2218+
child: const ColoredBox(
2219+
color: Colors.pink,
2220+
),
2221+
),
2222+
itemBuilder: (BuildContext context) {
2223+
return <PopupMenuEntry<int>>[
2224+
PopupMenuItem<int>(
2225+
value: 1,
2226+
child: Builder(
2227+
builder: (BuildContext context) {
2228+
mediaQueryPadding = MediaQuery.of(context).padding;
2229+
return Text('-1-' * 500); // A long long text string.
2230+
},
2231+
),
2232+
),
2233+
const PopupMenuItem<int>(value: 2, child: Text('-2-')),
2234+
];
2235+
},
2236+
)],
2237+
),
2238+
body: const SizedBox.shrink(),
2239+
),
2240+
);
2241+
}
2242+
2243+
await tester.pumpWidget(buildFrame(20.0, 20.0));
2244+
2245+
await tester.tap(find.byKey(buttonKey));
2246+
await tester.pumpAndSettle();
2247+
2248+
final Offset button = tester.getTopRight(find.byKey(buttonKey));
2249+
expect(button, Offset(800.0 - padding.right, padding.top)); // The topPadding is 32.0.
2250+
2251+
final Offset popupMenuTopRight = tester.getTopRight(find.byType(SingleChildScrollView));
2252+
2253+
// The menu should be positioned directly next to the top of the button.
2254+
// The 8.0 pixels is [_kMenuScreenPadding].
2255+
expect(popupMenuTopRight, Offset(800.0 - padding.right - 8.0, padding.top + 8.0));
2256+
2257+
final Offset popupMenuTopLeft = tester.getTopLeft(find.byType(SingleChildScrollView));
2258+
expect(popupMenuTopLeft, Offset(padding.left + 8.0, padding.top + 8.0));
2259+
2260+
final Offset popupMenuBottomLeft = tester.getBottomLeft(find.byType(SingleChildScrollView));
2261+
expect(popupMenuBottomLeft, Offset(padding.left + 8.0, 600.0 - padding.bottom - 8.0));
2262+
2263+
// The `MediaQueryData.padding` should be removed.
2264+
expect(mediaQueryPadding, EdgeInsets.zero);
2265+
});
2266+
21942267
group('feedback', () {
21952268
late FeedbackTester feedback;
21962269

0 commit comments

Comments
 (0)