diff --git a/packages/flutter/lib/src/material/menu_anchor.dart b/packages/flutter/lib/src/material/menu_anchor.dart index 451da7ca109..a496dd88513 100644 --- a/packages/flutter/lib/src/material/menu_anchor.dart +++ b/packages/flutter/lib/src/material/menu_anchor.dart @@ -1071,7 +1071,7 @@ class _MenuItemButtonState extends State { @override void didUpdateWidget(MenuItemButton oldWidget) { if (widget.focusNode != oldWidget.focusNode) { - _focusNode.removeListener(_handleFocusChange); + (oldWidget.focusNode ?? _internalFocusNode)?.removeListener(_handleFocusChange); if (widget.focusNode != null) { _internalFocusNode?.dispose(); _internalFocusNode = null; diff --git a/packages/flutter/test/material/menu_anchor_test.dart b/packages/flutter/test/material/menu_anchor_test.dart index a9fce196a62..a18aacd8042 100644 --- a/packages/flutter/test/material/menu_anchor_test.dart +++ b/packages/flutter/test/material/menu_anchor_test.dart @@ -2599,6 +2599,57 @@ void main() { ); }); + testWidgets('tapping MenuItemButton with null focus node', (WidgetTester tester) async { + + FocusNode? buttonFocusNode = FocusNode(); + + // Build our app and trigger a frame. + await tester.pumpWidget( + MaterialApp( + home: StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return MenuAnchor( + menuChildren: [ + MenuItemButton( + focusNode: buttonFocusNode, + closeOnActivate: false, + child: const Text('Set focus to null'), + onPressed: () { + setState((){ + buttonFocusNode = null; + }); + }, + ), + ], + builder: (BuildContext context, MenuController controller, Widget? child) { + return TextButton( + onPressed: () { + if (controller.isOpen) { + controller.close(); + } else { + controller.open(); + } + }, + child: const Text('OPEN MENU'), + ); + }, + ); + } + ), + ), + ); + + await tester.tap(find.text('OPEN MENU')); + await tester.pump(); + + expect(find.text('Set focus to null'), findsOneWidget); + + await tester.tap(find.text('Set focus to null')); + await tester.pumpAndSettle(); + + expect(tester.takeException(), isNull); + }); + testWidgets('constrained menus show up in the right place in RTL', (WidgetTester tester) async { await changeSurfaceSize(tester, const Size(300, 300)); await tester.pumpWidget(