From a35d6615eea4e50d05211c09d8cb3063e469762b Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Tue, 4 Jun 2019 10:39:08 -0700 Subject: [PATCH] Double double tap toggles instead of error (#33802) Fix exception that was happening when double-double-tapping a TextField (or double long tapping). --- .../flutter/lib/src/material/text_field.dart | 16 +++-- .../test/material/text_field_test.dart | 64 +++++++++++++++++++ 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/packages/flutter/lib/src/material/text_field.dart b/packages/flutter/lib/src/material/text_field.dart index 66ea57698d8..1d8aef085f1 100644 --- a/packages/flutter/lib/src/material/text_field.dart +++ b/packages/flutter/lib/src/material/text_field.dart @@ -744,8 +744,9 @@ class _TextFieldState extends State with AutomaticKeepAliveClientMixi from: details.globalPosition, cause: SelectionChangedCause.forcePress, ); - if (_shouldShowSelectionToolbar) - _editableTextKey.currentState.showToolbar(); + if (_shouldShowSelectionToolbar) { + _editableTextKey.currentState.toggleToolbar(); + } } } @@ -812,15 +813,18 @@ class _TextFieldState extends State with AutomaticKeepAliveClientMixi } void _handleSingleLongTapEnd(LongPressEndDetails details) { - if (_shouldShowSelectionToolbar) - _editableTextKey.currentState.showToolbar(); + if (widget.selectionEnabled) { + if (_shouldShowSelectionToolbar) + _editableTextKey.currentState.toggleToolbar(); + } } void _handleDoubleTapDown(TapDownDetails details) { if (widget.selectionEnabled) { _renderEditable.selectWord(cause: SelectionChangedCause.doubleTap); - if (_shouldShowSelectionToolbar) - _editableTextKey.currentState.showToolbar(); + if (_shouldShowSelectionToolbar) { + _editableText.toggleToolbar(); + } } } diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart index 22fede4503a..9316be65ecd 100644 --- a/packages/flutter/test/material/text_field_test.dart +++ b/packages/flutter/test/material/text_field_test.dart @@ -5220,6 +5220,70 @@ void main() { }, ); + testWidgets( + 'double double tap toggles selection menu', + (WidgetTester tester) async { + final TextEditingController controller = TextEditingController( + text: '', + ); + await tester.pumpWidget( + MaterialApp( + home: Material( + child: Center( + child: TextField( + controller: controller, + ), + ), + ), + ), + ); + + // Double tap on the same location shows the selection menu. + await tester.tapAt(textOffsetToPosition(tester, 0)); + await tester.pump(const Duration(milliseconds: 50)); + await tester.tapAt(textOffsetToPosition(tester, 0)); + await tester.pump(); + expect(find.text('PASTE'), findsOneWidget); + + // Double tap again hides the selection menu. + await tester.tapAt(textOffsetToPosition(tester, 0)); + await tester.pump(const Duration(milliseconds: 50)); + await tester.tapAt(textOffsetToPosition(tester, 0)); + await tester.pump(); + expect(find.text('PASTE'), findsNWidgets(0)); + }, + ); + + testWidgets( + 'double long press toggles selection menu', + (WidgetTester tester) async { + final TextEditingController controller = TextEditingController( + text: '', + ); + await tester.pumpWidget( + MaterialApp( + home: Material( + child: Center( + child: TextField( + controller: controller, + ), + ), + ), + ), + ); + + // Long press shows the selection menu. + await tester.longPressAt(textOffsetToPosition(tester, 0)); + await tester.pump(); + expect(find.text('PASTE'), findsOneWidget); + + // Double tap again hides the selection menu. + await tester.longPressAt(textOffsetToPosition(tester, 0)); + await tester.pump(); + expect(find.text('PASTE'), findsNWidgets(0)); + }, + ); + testWidgets( 'double tap hold selects word (iOS)', (WidgetTester tester) async {