diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 7f11ef799122..0a6270c416fd 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -3181,11 +3181,20 @@ class EditableTextState extends State with AutomaticKeepAliveClien bringIntoView(newSelection.extent); } + Object? _hideToolbarIfVisible(DismissIntent intent) { + if (_selectionOverlay?.toolbarIsVisible ?? false) { + hideToolbar(false); + return null; + } + return Actions.invoke(context, intent); + } + late final Map> _actions = >{ DoNothingAndStopPropagationTextIntent: DoNothingAction(consumesKey: false), ReplaceTextIntent: _replaceTextAction, UpdateSelectionIntent: _updateSelectionAction, DirectionalFocusIntent: DirectionalFocusAction.forTextField(), + DismissIntent: CallbackAction(onInvoke: _hideToolbarIfVisible), // Delete DeleteCharacterIntent: _makeOverridable(_DeleteTextAction(this, _characterBoundary)), diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index f113f23cba46..eff24bb40357 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -1318,6 +1318,41 @@ void main() { expect(find.text('Paste'), kIsWeb ? findsNothing : findsOneWidget); }); + testWidgets('can hide toolbar with DismissIntent', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: EditableText( + backgroundCursorColor: Colors.grey, + controller: controller, + focusNode: focusNode, + style: textStyle, + cursorColor: cursorColor, + selectionControls: materialTextSelectionControls, + ), + ), + ); + + final EditableTextState state = + tester.state(find.byType(EditableText)); + + // Show the toolbar + state.renderEditable.selectWordsInRange( + from: Offset.zero, + cause: SelectionChangedCause.tap, + ); + await tester.pump(); + + // On web, we don't let Flutter show the toolbar. + expect(state.showToolbar(), kIsWeb ? isFalse : isTrue); + await tester.pumpAndSettle(); + expect(find.text('Paste'), kIsWeb ? findsNothing : findsOneWidget); + + // Hide the menu using the DismissIntent. + await tester.sendKeyEvent(LogicalKeyboardKey.escape); + await tester.pump(); + expect(find.text('Paste'), findsNothing); + }); + testWidgets('Paste is shown only when there is something to paste', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp(