Unverified Commit 2b21c3e1 authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Shift tap gesture (#93835)

parent c44424b6
...@@ -86,33 +86,7 @@ class _TextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDete ...@@ -86,33 +86,7 @@ class _TextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDete
@override @override
void onSingleTapUp(TapUpDetails details) { void onSingleTapUp(TapUpDetails details) {
editableText.hideToolbar(); editableText.hideToolbar();
if (delegate.selectionEnabled) { super.onSingleTapUp(details);
switch (Theme.of(_state.context).platform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
switch (details.kind) {
case PointerDeviceKind.mouse:
case PointerDeviceKind.stylus:
case PointerDeviceKind.invertedStylus:
// Precise devices should place the cursor at a precise position.
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
case PointerDeviceKind.touch:
case PointerDeviceKind.unknown:
// On macOS/iOS/iPadOS a touch tap places the cursor at the edge
// of the word.
renderEditable.selectWordEdge(cause: SelectionChangedCause.tap);
break;
}
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
}
}
_state._requestKeyboard(); _state._requestKeyboard();
_state.widget.onTap?.call(); _state.widget.onTap?.call();
} }
......
...@@ -946,6 +946,65 @@ class TextSelectionGestureDetectorBuilder { ...@@ -946,6 +946,65 @@ class TextSelectionGestureDetectorBuilder {
&& renderEditable.selection!.end >= textPosition.offset; && renderEditable.selection!.end >= textPosition.offset;
} }
// Expand the selection to the given global position.
//
// Either base or extent will be moved to the last tapped position, whichever
// is closest. The selection will never shrink or pivot, only grow.
//
// See also:
//
// * [_extendSelection], which is similar but pivots the selection around
// the base.
void _expandSelection(Offset offset, SelectionChangedCause cause) {
assert(cause != null);
assert(offset != null);
assert(renderEditable.selection?.baseOffset != null);
final TextPosition tappedPosition = renderEditable.getPositionForPoint(offset);
final TextSelection selection = renderEditable.selection!;
final bool baseIsCloser =
(tappedPosition.offset - selection.baseOffset).abs()
< (tappedPosition.offset - selection.extentOffset).abs();
final TextSelection nextSelection = selection.copyWith(
baseOffset: baseIsCloser ? selection.extentOffset : selection.baseOffset,
extentOffset: tappedPosition.offset,
);
editableText.userUpdateTextEditingValue(
editableText.textEditingValue.copyWith(
selection: nextSelection,
),
cause,
);
}
// Extend the selection to the given global position.
//
// Holds the base in place and moves the extent.
//
// See also:
//
// * [_expandSelection], which is similar but always increases the size of
// the selection.
void _extendSelection(Offset offset, SelectionChangedCause cause) {
assert(cause != null);
assert(offset != null);
assert(renderEditable.selection?.baseOffset != null);
final TextPosition tappedPosition = renderEditable.getPositionForPoint(offset);
final TextSelection selection = renderEditable.selection!;
final TextSelection nextSelection = selection.copyWith(
extentOffset: tappedPosition.offset,
);
editableText.userUpdateTextEditingValue(
editableText.textEditingValue.copyWith(
selection: nextSelection,
),
cause,
);
}
/// Whether to show the selection toolbar. /// Whether to show the selection toolbar.
/// ///
/// It is based on the signal source when a [onTapDown] is called. This getter /// It is based on the signal source when a [onTapDown] is called. This getter
...@@ -964,9 +1023,12 @@ class TextSelectionGestureDetectorBuilder { ...@@ -964,9 +1023,12 @@ class TextSelectionGestureDetectorBuilder {
@protected @protected
RenderEditable get renderEditable => editableText.renderEditable; RenderEditable get renderEditable => editableText.renderEditable;
/// The viewport offset pixels of the [RenderEditable] at the last drag start. // The viewport offset pixels of the [RenderEditable] at the last drag start.
double _dragStartViewportOffset = 0.0; double _dragStartViewportOffset = 0.0;
// True iff a tap + shift has been detected but the tap has not yet come up.
bool _isShiftTapping = false;
/// Handler for [TextSelectionGestureDetector.onTapDown]. /// Handler for [TextSelectionGestureDetector.onTapDown].
/// ///
/// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets /// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets
...@@ -986,6 +1048,28 @@ class TextSelectionGestureDetectorBuilder { ...@@ -986,6 +1048,28 @@ class TextSelectionGestureDetectorBuilder {
_shouldShowSelectionToolbar = kind == null _shouldShowSelectionToolbar = kind == null
|| kind == PointerDeviceKind.touch || kind == PointerDeviceKind.touch
|| kind == PointerDeviceKind.stylus; || kind == PointerDeviceKind.stylus;
// Handle shift + click selection if needed.
final bool isShiftPressed = HardwareKeyboard.instance.logicalKeysPressed
.any(<LogicalKeyboardKey>{
LogicalKeyboardKey.shiftLeft,
LogicalKeyboardKey.shiftRight,
}.contains);
if (isShiftPressed && renderEditable.selection?.baseOffset != null) {
_isShiftTapping = true;
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
_expandSelection(details.globalPosition, SelectionChangedCause.tap);
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
_extendSelection(details.globalPosition, SelectionChangedCause.tap);
break;
}
}
} }
/// Handler for [TextSelectionGestureDetector.onForcePressStart]. /// Handler for [TextSelectionGestureDetector.onForcePressStart].
...@@ -1043,8 +1127,37 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1043,8 +1127,37 @@ class TextSelectionGestureDetectorBuilder {
/// this callback. /// this callback.
@protected @protected
void onSingleTapUp(TapUpDetails details) { void onSingleTapUp(TapUpDetails details) {
if (_isShiftTapping) {
_isShiftTapping = false;
return;
}
if (delegate.selectionEnabled) { if (delegate.selectionEnabled) {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
switch (details.kind) {
case PointerDeviceKind.mouse:
case PointerDeviceKind.stylus:
case PointerDeviceKind.invertedStylus:
// Precise devices should place the cursor at a precise position.
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
case PointerDeviceKind.touch:
case PointerDeviceKind.unknown:
// On macOS/iOS/iPadOS a touch tap places the cursor at the edge
// of the word.
renderEditable.selectWordEdge(cause: SelectionChangedCause.tap); renderEditable.selectWordEdge(cause: SelectionChangedCause.tap);
break;
}
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
}
} }
} }
......
...@@ -16,7 +16,7 @@ import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle, Color; ...@@ -16,7 +16,7 @@ import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle, Color;
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart' show DragStartBehavior, PointerDeviceKind, kSecondaryMouseButton; import 'package:flutter/gestures.dart' show DragStartBehavior, PointerDeviceKind, kSecondaryMouseButton, kDoubleTapTimeout;
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -1672,8 +1672,7 @@ void main() { ...@@ -1672,8 +1672,7 @@ void main() {
// But don't trigger the toolbar. // But don't trigger the toolbar.
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
);
testWidgets( testWidgets(
'slow double tap does not trigger double tap', 'slow double tap does not trigger double tap',
...@@ -1706,8 +1705,7 @@ void main() { ...@@ -1706,8 +1705,7 @@ void main() {
// No toolbar. // No toolbar.
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
);
testWidgets( testWidgets(
'double tap selects word and first tap of double tap moves cursor', 'double tap selects word and first tap of double tap moves cursor',
...@@ -1807,8 +1805,7 @@ void main() { ...@@ -1807,8 +1805,7 @@ void main() {
// Selected text shows 3 toolbar buttons. // Selected text shows 3 toolbar buttons.
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3)); expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3));
}, }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
);
testWidgets( testWidgets(
'double tap hold selects word', 'double tap hold selects word',
...@@ -1897,8 +1894,7 @@ void main() { ...@@ -1897,8 +1894,7 @@ void main() {
// No toolbar. // No toolbar.
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
);
testWidgets('double tapping a space selects the previous word on iOS', (WidgetTester tester) async { testWidgets('double tapping a space selects the previous word on iOS', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
...@@ -2292,8 +2288,7 @@ void main() { ...@@ -2292,8 +2288,7 @@ void main() {
// The toolbar from the long press is now dismissed by the second tap. // The toolbar from the long press is now dismissed by the second tap.
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
);
testWidgets( testWidgets(
'long press drag moves the cursor under the drag and shows toolbar on lift', 'long press drag moves the cursor under the drag and shows toolbar on lift',
...@@ -2485,8 +2480,7 @@ void main() { ...@@ -2485,8 +2480,7 @@ void main() {
// Long press toolbar. // Long press toolbar.
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(2)); expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(2));
}, }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
);
testWidgets( testWidgets(
'double tap after a long tap is not affected', 'double tap after a long tap is not affected',
...@@ -2526,8 +2520,7 @@ void main() { ...@@ -2526,8 +2520,7 @@ void main() {
); );
// Shows toolbar. // Shows toolbar.
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3)); expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3));
}, }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
);
testWidgets( testWidgets(
'double tap chains work', 'double tap chains work',
...@@ -2591,8 +2584,7 @@ void main() { ...@@ -2591,8 +2584,7 @@ void main() {
const TextSelection(baseOffset: 8, extentOffset: 12), const TextSelection(baseOffset: 8, extentOffset: 12),
); );
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3)); expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3));
}, }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
);
testWidgets('force press selects word', (WidgetTester tester) async { testWidgets('force press selects word', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
...@@ -2673,7 +2665,7 @@ void main() { ...@@ -2673,7 +2665,7 @@ void main() {
await tester.pump(); await tester.pump();
// Falling back to a single tap doesn't trigger a toolbar. // Falling back to a single tap doesn't trigger a toolbar.
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Cannot drag one handle past the other', (WidgetTester tester) async { testWidgets('Cannot drag one handle past the other', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
...@@ -2735,7 +2727,7 @@ void main() { ...@@ -2735,7 +2727,7 @@ void main() {
// The selection doesn't move beyond the left handle. There's always at // The selection doesn't move beyond the left handle. There's always at
// least 1 char selected. // least 1 char selected.
expect(controller.selection.extentOffset, 5); expect(controller.selection.extentOffset, 5);
}); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Can select text by dragging with a mouse', (WidgetTester tester) async { testWidgets('Can select text by dragging with a mouse', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
...@@ -4492,7 +4484,10 @@ void main() { ...@@ -4492,7 +4484,10 @@ void main() {
find.byType(CupertinoApp), find.byType(CupertinoApp),
matchesGoldenFile('text_field_golden.TextSelectionStyle.1.png'), matchesGoldenFile('text_field_golden.TextSelectionStyle.1.png'),
); );
}); },
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
skip: kIsWeb, // [intended] the web has its own Select All.
);
testWidgets('text selection style 2', (WidgetTester tester) async { testWidgets('text selection style 2', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
...@@ -4538,7 +4533,10 @@ void main() { ...@@ -4538,7 +4533,10 @@ void main() {
find.byType(CupertinoApp), find.byType(CupertinoApp),
matchesGoldenFile('text_field_golden.TextSelectionStyle.2.png'), matchesGoldenFile('text_field_golden.TextSelectionStyle.2.png'),
); );
}); },
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
skip: kIsWeb, // [intended] the web has its own Select All.
);
testWidgets('textSelectionControls is passed to EditableText', (WidgetTester tester) async { testWidgets('textSelectionControls is passed to EditableText', (WidgetTester tester) async {
final MockTextSelectionControls selectionControl = MockTextSelectionControls(); final MockTextSelectionControls selectionControl = MockTextSelectionControls();
...@@ -4877,4 +4875,92 @@ void main() { ...@@ -4877,4 +4875,92 @@ void main() {
matchesGoldenFile('overflow_clipbehavior_none.cupertino.0.png'), matchesGoldenFile('overflow_clipbehavior_none.cupertino.0.png'),
); );
}); });
testWidgets('can shift + tap to select with a keyboard (Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: CupertinoTextField(
controller: controller,
),
),
),
);
await tester.tapAt(textOffsetToPosition(tester, 13));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 13);
await tester.pump(kDoubleTapTimeout);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 20));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 20);
await tester.pump(kDoubleTapTimeout);
await tester.tapAt(textOffsetToPosition(tester, 23));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 23);
await tester.pump(kDoubleTapTimeout);
await tester.tapAt(textOffsetToPosition(tester, 4));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 23);
expect(controller.selection.extentOffset, 4);
await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
expect(controller.selection.baseOffset, 23);
expect(controller.selection.extentOffset, 4);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('can shift + tap to select with a keyboard (non-Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: CupertinoTextField(
controller: controller,
),
),
),
);
await tester.tapAt(textOffsetToPosition(tester, 13));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 13);
await tester.pump(kDoubleTapTimeout);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 20));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 20);
await tester.pump(kDoubleTapTimeout);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 23));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 23);
await tester.pump(kDoubleTapTimeout);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 4));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 4);
await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 4);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));
} }
...@@ -10512,4 +10512,92 @@ void main() { ...@@ -10512,4 +10512,92 @@ void main() {
await tester.pump(state.cursorBlinkInterval); await tester.pump(state.cursorBlinkInterval);
expect(editable.showCursor.value, isTrue); expect(editable.showCursor.value, isTrue);
}); });
testWidgets('can shift + tap to select with a keyboard (Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: TextField(controller: controller),
),
),
),
);
await tester.tapAt(textOffsetToPosition(tester, 13));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 13);
await tester.pump(kDoubleTapTimeout);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 20));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 20);
await tester.pump(kDoubleTapTimeout);
await tester.tapAt(textOffsetToPosition(tester, 23));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 23);
await tester.pump(kDoubleTapTimeout);
await tester.tapAt(textOffsetToPosition(tester, 4));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 23);
expect(controller.selection.extentOffset, 4);
await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
expect(controller.selection.baseOffset, 23);
expect(controller.selection.extentOffset, 4);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('can shift + tap to select with a keyboard (non-Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: TextField(controller: controller),
),
),
),
);
await tester.tapAt(textOffsetToPosition(tester, 13));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 13);
await tester.pump(kDoubleTapTimeout);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 20));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 20);
await tester.pump(kDoubleTapTimeout);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 23));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 23);
await tester.pump(kDoubleTapTimeout);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 4));
await tester.pumpAndSettle();
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 4);
await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
expect(controller.selection.baseOffset, 13);
expect(controller.selection.extentOffset, 4);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton; import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -506,8 +507,20 @@ void main() { ...@@ -506,8 +507,20 @@ void main() {
final FakeEditableTextState state = tester.state(find.byType(FakeEditableText)); final FakeEditableTextState state = tester.state(find.byType(FakeEditableText));
final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable)); final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
expect(state.showToolbarCalled, isFalse); expect(state.showToolbarCalled, isFalse);
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
expect(renderEditable.selectWordEdgeCalled, isTrue); expect(renderEditable.selectWordEdgeCalled, isTrue);
}); break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
expect(renderEditable.selectPositionAtCalled, isTrue);
break;
}
}, variant: TargetPlatformVariant.all());
testWidgets('test TextSelectionGestureDetectorBuilder double tap', (WidgetTester tester) async { testWidgets('test TextSelectionGestureDetectorBuilder double tap', (WidgetTester tester) async {
await pumpTextSelectionGestureDetectorBuilder(tester); await pumpTextSelectionGestureDetectorBuilder(tester);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment