diff --git a/packages/material_ui/lib/src/menu_anchor.dart b/packages/material_ui/lib/src/menu_anchor.dart index 14fa9e6b15e..68a0c129e45 100644 --- a/packages/material_ui/lib/src/menu_anchor.dart +++ b/packages/material_ui/lib/src/menu_anchor.dart @@ -3697,6 +3697,7 @@ class _MenuPanelState extends State<_MenuPanel> { final EdgeInsetsGeometry padding = resolve((MenuStyle? style) => style?.padding) ?? EdgeInsets.zero; final Offset densityAdjustment = visualDensity.baseSizeAdjustment; + final MediaQueryData mediaQuery = MediaQuery.of(context); // Per the Material Design team: don't allow the VisualDensity // adjustment to reduce the width of the left/right padding. If we // did, VisualDensity.compact, the default for desktop/web, would @@ -3757,17 +3758,28 @@ class _MenuPanelState extends State<_MenuPanel> { ).copyWith(scrollbars: false, overscroll: false, physics: const ClampingScrollPhysics()), child: PrimaryScrollController( controller: scrollController, - child: Scrollbar( - thumbVisibility: displayScrollbar, - child: SingleChildScrollView( - controller: scrollController, - scrollDirection: widget.orientation, - child: Flex( - crossAxisAlignment: CrossAxisAlignment.start, - textDirection: Directionality.of(context), - direction: widget.orientation, - mainAxisSize: MainAxisSize.min, - children: children, + child: MediaQuery( + data: mediaQuery.removePadding( + removeLeft: true, + removeTop: true, + removeRight: true, + removeBottom: true, + ), + child: Scrollbar( + thumbVisibility: displayScrollbar, + child: MediaQuery( + data: mediaQuery, + child: SingleChildScrollView( + controller: scrollController, + scrollDirection: widget.orientation, + child: Flex( + crossAxisAlignment: CrossAxisAlignment.start, + textDirection: Directionality.of(context), + direction: widget.orientation, + mainAxisSize: MainAxisSize.min, + children: children, + ), + ), ), ), ), diff --git a/packages/material_ui/pending_changelogs/change_2026_08_14_menu_anchor_scrollbar.yaml b/packages/material_ui/pending_changelogs/change_2026_08_14_menu_anchor_scrollbar.yaml new file mode 100644 index 00000000000..9edf4d555bc --- /dev/null +++ b/packages/material_ui/pending_changelogs/change_2026_08_14_menu_anchor_scrollbar.yaml @@ -0,0 +1,3 @@ +changelog: | + - Fixes `MenuAnchor` scrollbars inheriting system safe-area padding. +version: patch diff --git a/packages/material_ui/test/menu_anchor_test.dart b/packages/material_ui/test/menu_anchor_test.dart index f54165756b3..6d989d5d683 100644 --- a/packages/material_ui/test/menu_anchor_test.dart +++ b/packages/material_ui/test/menu_anchor_test.dart @@ -566,6 +566,54 @@ void main() { expect(find.byType(Scrollbar).last, paints..rrect(color: const Color(0xff00ff00))); }, variant: TargetPlatformVariant.desktop()); + // Regression test for https://github.com/flutter/flutter/issues/188155. + testWidgets('Menu scrollbar does not inherit MediaQuery padding', (WidgetTester tester) async { + addTearDown(tester.view.reset); + tester.view.devicePixelRatio = 1.0; + tester.view.padding = const FakeViewPadding(bottom: 24.0); + EdgeInsets? menuItemPadding; + + await tester.pumpWidget( + MaterialApp( + home: Material( + child: MenuAnchor( + controller: controller, + style: const MenuStyle( + maximumSize: WidgetStatePropertyAll(Size.fromHeight(100.0)), + ), + menuChildren: [ + Builder( + builder: (BuildContext context) { + menuItemPadding = MediaQuery.paddingOf(context); + return MenuItemButton(onPressed: () {}, child: const Text('Item 0')); + }, + ), + for (int i = 1; i < 4; i++) MenuItemButton(onPressed: () {}, child: Text('Item $i')), + ], + builder: (BuildContext context, MenuController controller, Widget? child) { + return TextButton(onPressed: controller.open, child: const Text('Open menu')); + }, + ), + ), + ), + ); + + await tester.tap(find.text('Open menu')); + await tester.pumpAndSettle(); + + final CustomPaint scrollbarPaint = tester.widget( + find.descendant( + of: find.byType(Scrollbar), + matching: find.byWidgetPredicate( + (Widget widget) => widget is CustomPaint && widget.foregroundPainter is ScrollbarPainter, + ), + ), + ); + final scrollbarPainter = scrollbarPaint.foregroundPainter! as ScrollbarPainter; + expect(scrollbarPainter.padding, EdgeInsets.zero); + expect(menuItemPadding, const EdgeInsets.only(bottom: 24.0)); + }); + testWidgets('Focus is returned to previous focus before invoking onPressed', ( WidgetTester tester, ) async {