mirror of
https://github.com/flutter/flutter
synced 2024-08-27 12:00:58 +00:00
Shift tap gesture (#93835)
This commit is contained in:
parent
c44424b67d
commit
2b21c3e163
|
@ -86,33 +86,7 @@ class _TextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDete
|
|||
@override
|
||||
void onSingleTapUp(TapUpDetails details) {
|
||||
editableText.hideToolbar();
|
||||
if (delegate.selectionEnabled) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
super.onSingleTapUp(details);
|
||||
_state._requestKeyboard();
|
||||
_state.widget.onTap?.call();
|
||||
}
|
||||
|
|
|
@ -946,6 +946,65 @@ class TextSelectionGestureDetectorBuilder {
|
|||
&& 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.
|
||||
///
|
||||
/// It is based on the signal source when a [onTapDown] is called. This getter
|
||||
|
@ -964,9 +1023,12 @@ class TextSelectionGestureDetectorBuilder {
|
|||
@protected
|
||||
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;
|
||||
|
||||
// True iff a tap + shift has been detected but the tap has not yet come up.
|
||||
bool _isShiftTapping = false;
|
||||
|
||||
/// Handler for [TextSelectionGestureDetector.onTapDown].
|
||||
///
|
||||
/// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets
|
||||
|
@ -986,6 +1048,28 @@ class TextSelectionGestureDetectorBuilder {
|
|||
_shouldShowSelectionToolbar = kind == null
|
||||
|| kind == PointerDeviceKind.touch
|
||||
|| 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].
|
||||
|
@ -1043,8 +1127,37 @@ class TextSelectionGestureDetectorBuilder {
|
|||
/// this callback.
|
||||
@protected
|
||||
void onSingleTapUp(TapUpDetails details) {
|
||||
if (_isShiftTapping) {
|
||||
_isShiftTapping = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate.selectionEnabled) {
|
||||
renderEditable.selectWordEdge(cause: SelectionChangedCause.tap);
|
||||
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);
|
||||
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;
|
|||
|
||||
import 'package:flutter/cupertino.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/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
@ -1672,8 +1672,7 @@ void main() {
|
|||
|
||||
// But don't trigger the toolbar.
|
||||
expect(find.byType(CupertinoButton), findsNothing);
|
||||
},
|
||||
);
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
|
||||
testWidgets(
|
||||
'slow double tap does not trigger double tap',
|
||||
|
@ -1706,8 +1705,7 @@ void main() {
|
|||
|
||||
// No toolbar.
|
||||
expect(find.byType(CupertinoButton), findsNothing);
|
||||
},
|
||||
);
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
|
||||
testWidgets(
|
||||
'double tap selects word and first tap of double tap moves cursor',
|
||||
|
@ -1807,8 +1805,7 @@ void main() {
|
|||
|
||||
// Selected text shows 3 toolbar buttons.
|
||||
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3));
|
||||
},
|
||||
);
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
|
||||
testWidgets(
|
||||
'double tap hold selects word',
|
||||
|
@ -1897,8 +1894,7 @@ void main() {
|
|||
|
||||
// No toolbar.
|
||||
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 {
|
||||
final TextEditingController controller = TextEditingController(
|
||||
|
@ -2292,8 +2288,7 @@ void main() {
|
|||
|
||||
// The toolbar from the long press is now dismissed by the second tap.
|
||||
expect(find.byType(CupertinoButton), findsNothing);
|
||||
},
|
||||
);
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
|
||||
testWidgets(
|
||||
'long press drag moves the cursor under the drag and shows toolbar on lift',
|
||||
|
@ -2485,8 +2480,7 @@ void main() {
|
|||
|
||||
// Long press toolbar.
|
||||
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(2));
|
||||
},
|
||||
);
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
|
||||
testWidgets(
|
||||
'double tap after a long tap is not affected',
|
||||
|
@ -2526,8 +2520,7 @@ void main() {
|
|||
);
|
||||
// Shows toolbar.
|
||||
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3));
|
||||
},
|
||||
);
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
|
||||
testWidgets(
|
||||
'double tap chains work',
|
||||
|
@ -2591,8 +2584,7 @@ void main() {
|
|||
const TextSelection(baseOffset: 8, extentOffset: 12),
|
||||
);
|
||||
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(3));
|
||||
},
|
||||
);
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
|
||||
testWidgets('force press selects word', (WidgetTester tester) async {
|
||||
final TextEditingController controller = TextEditingController(
|
||||
|
@ -2673,7 +2665,7 @@ void main() {
|
|||
await tester.pump();
|
||||
// Falling back to a single tap doesn't trigger a toolbar.
|
||||
expect(find.byType(CupertinoButton), findsNothing);
|
||||
});
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
|
||||
testWidgets('Cannot drag one handle past the other', (WidgetTester tester) async {
|
||||
final TextEditingController controller = TextEditingController(
|
||||
|
@ -2735,7 +2727,7 @@ void main() {
|
|||
// The selection doesn't move beyond the left handle. There's always at
|
||||
// least 1 char selected.
|
||||
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 {
|
||||
final TextEditingController controller = TextEditingController();
|
||||
|
@ -4492,7 +4484,10 @@ void main() {
|
|||
find.byType(CupertinoApp),
|
||||
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 {
|
||||
final TextEditingController controller = TextEditingController(
|
||||
|
@ -4538,7 +4533,10 @@ void main() {
|
|||
find.byType(CupertinoApp),
|
||||
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 {
|
||||
final MockTextSelectionControls selectionControl = MockTextSelectionControls();
|
||||
|
@ -4877,4 +4875,92 @@ void main() {
|
|||
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() {
|
|||
await tester.pump(state.cursorBlinkInterval);
|
||||
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 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
|
||||
import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
@ -506,8 +507,20 @@ void main() {
|
|||
final FakeEditableTextState state = tester.state(find.byType(FakeEditableText));
|
||||
final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
|
||||
expect(state.showToolbarCalled, isFalse);
|
||||
expect(renderEditable.selectWordEdgeCalled, isTrue);
|
||||
});
|
||||
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.iOS:
|
||||
case TargetPlatform.macOS:
|
||||
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 {
|
||||
await pumpTextSelectionGestureDetectorBuilder(tester);
|
||||
|
|
Loading…
Reference in a new issue