This reverts commit 46878d848566769e51f21407de2fead528c1d2c4.
This commit is contained in:
parent
46878d8485
commit
4cd87705b7
@ -672,7 +672,6 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
|
|||||||
cursorWidth: widget.cursorWidth,
|
cursorWidth: widget.cursorWidth,
|
||||||
cursorRadius: widget.cursorRadius,
|
cursorRadius: widget.cursorRadius,
|
||||||
cursorColor: widget.cursorColor,
|
cursorColor: widget.cursorColor,
|
||||||
backgroundCursorColor: CupertinoColors.inactiveGray,
|
|
||||||
scrollPadding: widget.scrollPadding,
|
scrollPadding: widget.scrollPadding,
|
||||||
keyboardAppearance: keyboardAppearance,
|
keyboardAppearance: keyboardAppearance,
|
||||||
),
|
),
|
||||||
|
@ -613,7 +613,6 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
|
|||||||
cursorWidth: widget.cursorWidth,
|
cursorWidth: widget.cursorWidth,
|
||||||
cursorRadius: widget.cursorRadius,
|
cursorRadius: widget.cursorRadius,
|
||||||
cursorColor: widget.cursorColor ?? Theme.of(context).cursorColor,
|
cursorColor: widget.cursorColor ?? Theme.of(context).cursorColor,
|
||||||
backgroundCursorColor: CupertinoColors.inactiveGray,
|
|
||||||
scrollPadding: widget.scrollPadding,
|
scrollPadding: widget.scrollPadding,
|
||||||
keyboardAppearance: keyboardAppearance,
|
keyboardAppearance: keyboardAppearance,
|
||||||
enableInteractiveSelection: widget.enableInteractiveSelection,
|
enableInteractiveSelection: widget.enableInteractiveSelection,
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
//ignore: Remove this once Google catches up with dev.4 Dart.
|
//ignore: Remove this once Google catches up with dev.4 Dart.
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'dart:ui' as ui show TextBox, lerpDouble;
|
import 'dart:ui' as ui show TextBox;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
@ -19,13 +19,6 @@ import 'viewport_offset.dart';
|
|||||||
const double _kCaretGap = 1.0; // pixels
|
const double _kCaretGap = 1.0; // pixels
|
||||||
const double _kCaretHeightOffset = 2.0; // pixels
|
const double _kCaretHeightOffset = 2.0; // pixels
|
||||||
|
|
||||||
// The additional size on the x and y axis with which to expand the prototype
|
|
||||||
// cursor to render the floating cursor in pixels.
|
|
||||||
const Offset _kFloatingCaretSizeIncrease = Offset(0.5, 2.0);
|
|
||||||
|
|
||||||
// The corner radius of the floating cursor in pixels.
|
|
||||||
const double _kFloatingCaretRadius = 1.0;
|
|
||||||
|
|
||||||
/// Signature for the callback that reports when the user changes the selection
|
/// Signature for the callback that reports when the user changes the selection
|
||||||
/// (including the cursor location).
|
/// (including the cursor location).
|
||||||
///
|
///
|
||||||
@ -136,7 +129,6 @@ class RenderEditable extends RenderBox {
|
|||||||
@required TextDirection textDirection,
|
@required TextDirection textDirection,
|
||||||
TextAlign textAlign = TextAlign.start,
|
TextAlign textAlign = TextAlign.start,
|
||||||
Color cursorColor,
|
Color cursorColor,
|
||||||
Color backgroundCursorColor,
|
|
||||||
ValueNotifier<bool> showCursor,
|
ValueNotifier<bool> showCursor,
|
||||||
bool hasFocus,
|
bool hasFocus,
|
||||||
int maxLines = 1,
|
int maxLines = 1,
|
||||||
@ -151,7 +143,6 @@ class RenderEditable extends RenderBox {
|
|||||||
Locale locale,
|
Locale locale,
|
||||||
double cursorWidth = 1.0,
|
double cursorWidth = 1.0,
|
||||||
Radius cursorRadius,
|
Radius cursorRadius,
|
||||||
EdgeInsets floatingCursorAddedMargin = const EdgeInsets.fromLTRB(3, 6, 3, 6),
|
|
||||||
bool enableInteractiveSelection = true,
|
bool enableInteractiveSelection = true,
|
||||||
@required this.textSelectionDelegate,
|
@required this.textSelectionDelegate,
|
||||||
}) : assert(textAlign != null),
|
}) : assert(textAlign != null),
|
||||||
@ -171,7 +162,6 @@ class RenderEditable extends RenderBox {
|
|||||||
locale: locale,
|
locale: locale,
|
||||||
),
|
),
|
||||||
_cursorColor = cursorColor,
|
_cursorColor = cursorColor,
|
||||||
_backgroundCursorColor = backgroundCursorColor,
|
|
||||||
_showCursor = showCursor ?? ValueNotifier<bool>(false),
|
_showCursor = showCursor ?? ValueNotifier<bool>(false),
|
||||||
_hasFocus = hasFocus ?? false,
|
_hasFocus = hasFocus ?? false,
|
||||||
_maxLines = maxLines,
|
_maxLines = maxLines,
|
||||||
@ -180,7 +170,6 @@ class RenderEditable extends RenderBox {
|
|||||||
_offset = offset,
|
_offset = offset,
|
||||||
_cursorWidth = cursorWidth,
|
_cursorWidth = cursorWidth,
|
||||||
_cursorRadius = cursorRadius,
|
_cursorRadius = cursorRadius,
|
||||||
_floatingCursorAddedMargin = floatingCursorAddedMargin,
|
|
||||||
_enableInteractiveSelection = enableInteractiveSelection,
|
_enableInteractiveSelection = enableInteractiveSelection,
|
||||||
_obscureText = obscureText {
|
_obscureText = obscureText {
|
||||||
assert(_showCursor != null);
|
assert(_showCursor != null);
|
||||||
@ -577,19 +566,6 @@ class RenderEditable extends RenderBox {
|
|||||||
markNeedsPaint();
|
markNeedsPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The color to use when painting the cursor aligned to the text while
|
|
||||||
/// rendering the floating cursor.
|
|
||||||
///
|
|
||||||
/// The default is light grey.
|
|
||||||
Color get backgroundCursorColor => _backgroundCursorColor;
|
|
||||||
Color _backgroundCursorColor;
|
|
||||||
set backgroundCursorColor(Color value) {
|
|
||||||
if (backgroundCursorColor == value)
|
|
||||||
return;
|
|
||||||
_backgroundCursorColor = value;
|
|
||||||
markNeedsPaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether to paint the cursor.
|
/// Whether to paint the cursor.
|
||||||
ValueNotifier<bool> get showCursor => _showCursor;
|
ValueNotifier<bool> get showCursor => _showCursor;
|
||||||
ValueNotifier<bool> _showCursor;
|
ValueNotifier<bool> _showCursor;
|
||||||
@ -725,23 +701,6 @@ class RenderEditable extends RenderBox {
|
|||||||
markNeedsPaint();
|
markNeedsPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The padding applied to text field. Used to determine the bounds when
|
|
||||||
/// moving the floating cursor.
|
|
||||||
///
|
|
||||||
/// Defaults to a padding with left, right set to 3 and top, bottom to 6.
|
|
||||||
EdgeInsets get floatingCursorAddedMargin => _floatingCursorAddedMargin;
|
|
||||||
EdgeInsets _floatingCursorAddedMargin;
|
|
||||||
set floatingCursorAddedMargin(EdgeInsets value) {
|
|
||||||
if (_floatingCursorAddedMargin == value)
|
|
||||||
return;
|
|
||||||
_floatingCursorAddedMargin = value;
|
|
||||||
markNeedsPaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _floatingCursorOn = false;
|
|
||||||
Offset _floatingCursorOffset;
|
|
||||||
TextPosition _floatingCursorTextPosition;
|
|
||||||
|
|
||||||
/// If false, [describeSemanticsConfiguration] will not set the
|
/// If false, [describeSemanticsConfiguration] will not set the
|
||||||
/// configuration's cursor motion or set selection callbacks.
|
/// configuration's cursor motion or set selection callbacks.
|
||||||
///
|
///
|
||||||
@ -1246,13 +1205,11 @@ class RenderEditable extends RenderBox {
|
|||||||
offset.applyContentDimensions(0.0, _maxScrollExtent);
|
offset.applyContentDimensions(0.0, _maxScrollExtent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _paintCaret(Canvas canvas, Offset effectiveOffset, TextPosition textPosition) {
|
void _paintCaret(Canvas canvas, Offset effectiveOffset) {
|
||||||
assert(_textLayoutLastWidth == constraints.maxWidth);
|
assert(_textLayoutLastWidth == constraints.maxWidth);
|
||||||
final Offset caretOffset = _textPainter.getOffsetForCaret(textPosition, _caretPrototype);
|
final Offset caretOffset = _textPainter.getOffsetForCaret(_selection.extent, _caretPrototype);
|
||||||
// If the floating cursor is enabled, the text cursor's color is [backgroundCursorColor] while
|
|
||||||
// the floating cursor's color is _cursorColor;
|
|
||||||
final Paint paint = Paint()
|
final Paint paint = Paint()
|
||||||
..color = _floatingCursorOn ? backgroundCursorColor : _cursorColor;
|
..color = _cursorColor;
|
||||||
|
|
||||||
final Rect caretRect = _caretPrototype.shift(caretOffset + effectiveOffset);
|
final Rect caretRect = _caretPrototype.shift(caretOffset + effectiveOffset);
|
||||||
|
|
||||||
@ -1270,112 +1227,6 @@ class RenderEditable extends RenderBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the screen position of the floating cursor and the text position
|
|
||||||
/// closest to the cursor.
|
|
||||||
void setFloatingCursor(FloatingCursorDragState state, Offset boundedOffset, TextPosition lastTextPosition, { double resetLerpValue }) {
|
|
||||||
assert(state != null);
|
|
||||||
assert(boundedOffset != null);
|
|
||||||
assert(lastTextPosition != null);
|
|
||||||
if (state == FloatingCursorDragState.Start) {
|
|
||||||
_relativeOrigin = const Offset(0, 0);
|
|
||||||
_previousOffset = null;
|
|
||||||
_resetOriginOnBottom = false;
|
|
||||||
_resetOriginOnTop = false;
|
|
||||||
_resetOriginOnRight = false;
|
|
||||||
_resetOriginOnBottom = false;
|
|
||||||
}
|
|
||||||
_floatingCursorOn = state != FloatingCursorDragState.End;
|
|
||||||
_resetFloatingCursorAnimationValue = resetLerpValue;
|
|
||||||
if(_floatingCursorOn) {
|
|
||||||
_floatingCursorOffset = boundedOffset;
|
|
||||||
_floatingCursorTextPosition = lastTextPosition;
|
|
||||||
}
|
|
||||||
markNeedsPaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _paintFloatingCaret(Canvas canvas, Offset effectiveOffset) {
|
|
||||||
assert(_textLayoutLastWidth == constraints.maxWidth);
|
|
||||||
assert(_floatingCursorOn);
|
|
||||||
|
|
||||||
final Paint paint = Paint()..color = _cursorColor;
|
|
||||||
|
|
||||||
double sizeAdjustmentX = _kFloatingCaretSizeIncrease.dx;
|
|
||||||
double sizeAdjustmentY = _kFloatingCaretSizeIncrease.dy;
|
|
||||||
|
|
||||||
if(_resetFloatingCursorAnimationValue != null) {
|
|
||||||
sizeAdjustmentX = ui.lerpDouble(sizeAdjustmentX, 0, _resetFloatingCursorAnimationValue);
|
|
||||||
sizeAdjustmentY = ui.lerpDouble(sizeAdjustmentY, 0, _resetFloatingCursorAnimationValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Rect floatingCaretPrototype = Rect.fromLTRB(_caretPrototype.left - sizeAdjustmentX,
|
|
||||||
_caretPrototype.top - sizeAdjustmentY,
|
|
||||||
_caretPrototype.right + sizeAdjustmentX,
|
|
||||||
_caretPrototype.bottom + sizeAdjustmentY);
|
|
||||||
final Rect caretRect = floatingCaretPrototype.shift(effectiveOffset);
|
|
||||||
const Radius floatingCursorRadius = Radius.circular(_kFloatingCaretRadius);
|
|
||||||
final RRect caretRRect = RRect.fromRectAndRadius(caretRect, floatingCursorRadius);
|
|
||||||
canvas.drawRRect(caretRRect, paint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The relative origin in relation to the distance the user has theoretically
|
|
||||||
// dragged the floating cursor offscreen. This value is used to account for the
|
|
||||||
// difference in the rendering position and the raw offset value.
|
|
||||||
Offset _relativeOrigin = const Offset(0, 0);
|
|
||||||
Offset _previousOffset;
|
|
||||||
bool _resetOriginOnLeft = false;
|
|
||||||
bool _resetOriginOnRight = false;
|
|
||||||
bool _resetOriginOnTop = false;
|
|
||||||
bool _resetOriginOnBottom = false;
|
|
||||||
double _resetFloatingCursorAnimationValue;
|
|
||||||
|
|
||||||
/// Returns the position within the text field closest to the raw cursor offset.
|
|
||||||
Offset calculateBoundedFloatingCursorOffset(Offset rawCursorOffset) {
|
|
||||||
Offset deltaPosition = const Offset(0, 0);
|
|
||||||
final double topBound = -floatingCursorAddedMargin.top;
|
|
||||||
final double bottomBound = _textPainter.height - preferredLineHeight + floatingCursorAddedMargin.bottom;
|
|
||||||
final double leftBound = -floatingCursorAddedMargin.left;
|
|
||||||
final double rightBound = _textPainter.width + floatingCursorAddedMargin.right;
|
|
||||||
|
|
||||||
if (_previousOffset != null)
|
|
||||||
deltaPosition = rawCursorOffset - _previousOffset;
|
|
||||||
|
|
||||||
// If the raw cursor offset has gone off an edge, we want to reset the relative
|
|
||||||
// origin of the dragging when the user drags back into the field.
|
|
||||||
if (_resetOriginOnLeft && deltaPosition.dx > 0) {
|
|
||||||
_relativeOrigin = Offset(rawCursorOffset.dx - leftBound, _relativeOrigin.dy);
|
|
||||||
_resetOriginOnLeft = false;
|
|
||||||
} else if (_resetOriginOnRight && deltaPosition.dx < 0) {
|
|
||||||
_relativeOrigin = Offset(rawCursorOffset.dx - rightBound, _relativeOrigin.dy);
|
|
||||||
_resetOriginOnRight = false;
|
|
||||||
}
|
|
||||||
if (_resetOriginOnTop && deltaPosition.dy > 0) {
|
|
||||||
_relativeOrigin = Offset(_relativeOrigin.dx, rawCursorOffset.dy - topBound);
|
|
||||||
_resetOriginOnTop = false;
|
|
||||||
} else if (_resetOriginOnBottom && deltaPosition.dy < 0) {
|
|
||||||
_relativeOrigin = Offset(_relativeOrigin.dx, rawCursorOffset.dy - bottomBound);
|
|
||||||
_resetOriginOnBottom = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final double currentX = rawCursorOffset.dx - _relativeOrigin.dx;
|
|
||||||
final double currentY = rawCursorOffset.dy - _relativeOrigin.dy;
|
|
||||||
final double adjustedX = math.min(math.max(currentX, leftBound), rightBound);
|
|
||||||
final double adjustedY = math.min(math.max(currentY, topBound), bottomBound);
|
|
||||||
final Offset adjustedOffset = Offset(adjustedX, adjustedY);
|
|
||||||
|
|
||||||
if (currentX < leftBound && deltaPosition.dx < 0) {
|
|
||||||
_resetOriginOnLeft = true;
|
|
||||||
} else if(currentX > rightBound && deltaPosition.dx > 0)
|
|
||||||
_resetOriginOnRight = true;
|
|
||||||
if (currentY < topBound && deltaPosition.dy < 0)
|
|
||||||
_resetOriginOnTop = true;
|
|
||||||
else if (currentY > bottomBound && deltaPosition.dy > 0)
|
|
||||||
_resetOriginOnBottom = true;
|
|
||||||
|
|
||||||
_previousOffset = rawCursorOffset;
|
|
||||||
|
|
||||||
return adjustedOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _paintSelection(Canvas canvas, Offset effectiveOffset) {
|
void _paintSelection(Canvas canvas, Offset effectiveOffset) {
|
||||||
assert(_textLayoutLastWidth == constraints.maxWidth);
|
assert(_textLayoutLastWidth == constraints.maxWidth);
|
||||||
assert(_selectionRects != null);
|
assert(_selectionRects != null);
|
||||||
@ -1387,20 +1238,17 @@ class RenderEditable extends RenderBox {
|
|||||||
void _paintContents(PaintingContext context, Offset offset) {
|
void _paintContents(PaintingContext context, Offset offset) {
|
||||||
assert(_textLayoutLastWidth == constraints.maxWidth);
|
assert(_textLayoutLastWidth == constraints.maxWidth);
|
||||||
final Offset effectiveOffset = offset + _paintOffset;
|
final Offset effectiveOffset = offset + _paintOffset;
|
||||||
if (_selection != null && !_floatingCursorOn) {
|
|
||||||
|
if (_selection != null) {
|
||||||
if (_selection.isCollapsed && _showCursor.value && cursorColor != null) {
|
if (_selection.isCollapsed && _showCursor.value && cursorColor != null) {
|
||||||
_paintCaret(context.canvas, effectiveOffset, _selection.extent);
|
_paintCaret(context.canvas, effectiveOffset);
|
||||||
} else if (!_selection.isCollapsed && _selectionColor != null) {
|
} else if (!_selection.isCollapsed && _selectionColor != null) {
|
||||||
_selectionRects ??= _textPainter.getBoxesForSelection(_selection);
|
_selectionRects ??= _textPainter.getBoxesForSelection(_selection);
|
||||||
_paintSelection(context.canvas, effectiveOffset);
|
_paintSelection(context.canvas, effectiveOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_textPainter.paint(context.canvas, effectiveOffset);
|
_textPainter.paint(context.canvas, effectiveOffset);
|
||||||
if (_floatingCursorOn) {
|
|
||||||
if (_resetFloatingCursorAnimationValue == null)
|
|
||||||
_paintCaret(context.canvas, effectiveOffset, _floatingCursorTextPosition);
|
|
||||||
_paintFloatingCaret(context.canvas, _floatingCursorOffset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io' show Platform;
|
import 'dart:io' show Platform;
|
||||||
import 'dart:ui' show TextAffinity, hashValues, Offset;
|
import 'dart:ui' show TextAffinity, hashValues;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
@ -439,40 +439,6 @@ TextAffinity _toTextAffinity(String affinity) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A floating cursor state the user has induced by force pressing an iOS
|
|
||||||
/// keyboard.
|
|
||||||
enum FloatingCursorDragState {
|
|
||||||
/// A user has just activated a floating cursor.
|
|
||||||
Start,
|
|
||||||
|
|
||||||
/// A user is dragging a floating cursor.
|
|
||||||
Update,
|
|
||||||
|
|
||||||
/// A user has lifted their finger off the screen after using a floating
|
|
||||||
/// cursor.
|
|
||||||
End,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The current state and position of the floating cursor.
|
|
||||||
class RawFloatingCursorPoint {
|
|
||||||
/// Creates information for setting the position and state of a floating
|
|
||||||
/// cursor.
|
|
||||||
///
|
|
||||||
/// [state] must not be null and [offset] must not be null if the state is
|
|
||||||
/// [FloatingCursorDragState.Update].
|
|
||||||
RawFloatingCursorPoint({
|
|
||||||
this.offset,
|
|
||||||
@required this.state,
|
|
||||||
}) : assert(state != null),
|
|
||||||
assert(state == FloatingCursorDragState.Update ? offset != null : true);
|
|
||||||
|
|
||||||
/// The raw position of the floating cursor as determined by the iOS sdk.
|
|
||||||
final Offset offset;
|
|
||||||
|
|
||||||
/// The state of the floating cursor.
|
|
||||||
final FloatingCursorDragState state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The current text, selection, and composing state for editing a run of text.
|
/// The current text, selection, and composing state for editing a run of text.
|
||||||
@immutable
|
@immutable
|
||||||
class TextEditingValue {
|
class TextEditingValue {
|
||||||
@ -600,9 +566,6 @@ abstract class TextInputClient {
|
|||||||
|
|
||||||
/// Requests that this client perform the given action.
|
/// Requests that this client perform the given action.
|
||||||
void performAction(TextInputAction action);
|
void performAction(TextInputAction action);
|
||||||
|
|
||||||
/// Updates the floating cursor position and state.
|
|
||||||
void updateFloatingCursor(RawFloatingCursorPoint point);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An interface for interacting with a text input control.
|
/// An interface for interacting with a text input control.
|
||||||
@ -685,26 +648,6 @@ TextInputAction _toTextInputAction(String action) {
|
|||||||
throw FlutterError('Unknown text input action: $action');
|
throw FlutterError('Unknown text input action: $action');
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingCursorDragState _toTextCursorAction(String state) {
|
|
||||||
switch (state) {
|
|
||||||
case 'FloatingCursorDragState.start':
|
|
||||||
return FloatingCursorDragState.Start;
|
|
||||||
case 'FloatingCursorDragState.update':
|
|
||||||
return FloatingCursorDragState.Update;
|
|
||||||
case 'FloatingCursorDragState.end':
|
|
||||||
return FloatingCursorDragState.End;
|
|
||||||
}
|
|
||||||
throw FlutterError('Unknown text cursor action: $state');
|
|
||||||
}
|
|
||||||
|
|
||||||
RawFloatingCursorPoint _toTextPoint(FloatingCursorDragState state, Map<String, dynamic> encoded) {
|
|
||||||
assert(state != null, 'You must provide a state to set a new editing point.');
|
|
||||||
assert(encoded['X'] != null, 'You must provide a value for the horizontal location of the floating cursor.');
|
|
||||||
assert(encoded['Y'] != null, 'You must provide a value for the vertical location of the floating cursor.');
|
|
||||||
final Offset offset = state == FloatingCursorDragState.Update ? Offset(encoded['X'], encoded['Y']) : const Offset(0, 0);
|
|
||||||
return RawFloatingCursorPoint(offset: offset, state: state);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _TextInputClientHandler {
|
class _TextInputClientHandler {
|
||||||
_TextInputClientHandler() {
|
_TextInputClientHandler() {
|
||||||
SystemChannels.textInput.setMethodCallHandler(_handleTextInputInvocation);
|
SystemChannels.textInput.setMethodCallHandler(_handleTextInputInvocation);
|
||||||
@ -728,9 +671,6 @@ class _TextInputClientHandler {
|
|||||||
case 'TextInputClient.performAction':
|
case 'TextInputClient.performAction':
|
||||||
_currentConnection._client.performAction(_toTextInputAction(args[1]));
|
_currentConnection._client.performAction(_toTextInputAction(args[1]));
|
||||||
break;
|
break;
|
||||||
case 'TextInputClient.updateFloatingCursor':
|
|
||||||
_currentConnection._client.updateFloatingCursor(_toTextPoint(_toTextCursorAction(args[1]), args[2]));
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw MissingPluginException();
|
throw MissingPluginException();
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ import 'scroll_controller.dart';
|
|||||||
import 'scroll_physics.dart';
|
import 'scroll_physics.dart';
|
||||||
import 'scrollable.dart';
|
import 'scrollable.dart';
|
||||||
import 'text_selection.dart';
|
import 'text_selection.dart';
|
||||||
import 'ticker_provider.dart';
|
|
||||||
|
|
||||||
export 'package:flutter/services.dart' show TextEditingValue, TextSelection, TextInputType;
|
export 'package:flutter/services.dart' show TextEditingValue, TextSelection, TextInputType;
|
||||||
export 'package:flutter/rendering.dart' show SelectionChangedCause;
|
export 'package:flutter/rendering.dart' show SelectionChangedCause;
|
||||||
@ -183,9 +182,9 @@ class EditableText extends StatefulWidget {
|
|||||||
/// [TextInputType.text] unless [maxLines] is greater than one, when it will
|
/// [TextInputType.text] unless [maxLines] is greater than one, when it will
|
||||||
/// default to [TextInputType.multiline].
|
/// default to [TextInputType.multiline].
|
||||||
///
|
///
|
||||||
/// The [controller], [focusNode], [style], [cursorColor], [backgroundCursorColor],
|
/// The [controller], [focusNode], [style], [cursorColor], [textAlign],
|
||||||
/// [textAlign], [rendererIgnoresPointer], and [enableInteractiveSelection]
|
/// [rendererIgnoresPointer], and [enableInteractiveSelection] arguments must
|
||||||
/// arguments must not be null.
|
/// not be null.
|
||||||
EditableText({
|
EditableText({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.controller,
|
@required this.controller,
|
||||||
@ -194,7 +193,6 @@ class EditableText extends StatefulWidget {
|
|||||||
this.autocorrect = true,
|
this.autocorrect = true,
|
||||||
@required this.style,
|
@required this.style,
|
||||||
@required this.cursorColor,
|
@required this.cursorColor,
|
||||||
@required this.backgroundCursorColor,
|
|
||||||
this.textAlign = TextAlign.start,
|
this.textAlign = TextAlign.start,
|
||||||
this.textDirection,
|
this.textDirection,
|
||||||
this.locale,
|
this.locale,
|
||||||
@ -223,7 +221,6 @@ class EditableText extends StatefulWidget {
|
|||||||
assert(autocorrect != null),
|
assert(autocorrect != null),
|
||||||
assert(style != null),
|
assert(style != null),
|
||||||
assert(cursorColor != null),
|
assert(cursorColor != null),
|
||||||
assert(backgroundCursorColor != null),
|
|
||||||
assert(textAlign != null),
|
assert(textAlign != null),
|
||||||
assert(maxLines == null || maxLines > 0),
|
assert(maxLines == null || maxLines > 0),
|
||||||
assert(autofocus != null),
|
assert(autofocus != null),
|
||||||
@ -327,13 +324,6 @@ class EditableText extends StatefulWidget {
|
|||||||
/// Cannot be null.
|
/// Cannot be null.
|
||||||
final Color cursorColor;
|
final Color cursorColor;
|
||||||
|
|
||||||
/// The color to use when painting the background cursor aligned with the text
|
|
||||||
/// while rendering the floating cursor.
|
|
||||||
///
|
|
||||||
/// Cannot be null. By default it is the disabled grey color from
|
|
||||||
/// CupertinoColors.
|
|
||||||
final Color backgroundCursorColor;
|
|
||||||
|
|
||||||
/// {@template flutter.widgets.editableText.maxLines}
|
/// {@template flutter.widgets.editableText.maxLines}
|
||||||
/// The maximum number of lines for the text to span, wrapping if necessary.
|
/// The maximum number of lines for the text to span, wrapping if necessary.
|
||||||
///
|
///
|
||||||
@ -501,7 +491,7 @@ class EditableText extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// State for a [EditableText].
|
/// State for a [EditableText].
|
||||||
class EditableTextState extends State<EditableText> with AutomaticKeepAliveClientMixin<EditableText>, WidgetsBindingObserver, TickerProviderStateMixin<EditableText> implements TextInputClient, TextSelectionDelegate {
|
class EditableTextState extends State<EditableText> with AutomaticKeepAliveClientMixin<EditableText>, WidgetsBindingObserver implements TextInputClient, TextSelectionDelegate {
|
||||||
Timer _cursorTimer;
|
Timer _cursorTimer;
|
||||||
final ValueNotifier<bool> _showCursor = ValueNotifier<bool>(false);
|
final ValueNotifier<bool> _showCursor = ValueNotifier<bool>(false);
|
||||||
final GlobalKey _editableKey = GlobalKey();
|
final GlobalKey _editableKey = GlobalKey();
|
||||||
@ -513,12 +503,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
final LayerLink _layerLink = LayerLink();
|
final LayerLink _layerLink = LayerLink();
|
||||||
bool _didAutoFocus = false;
|
bool _didAutoFocus = false;
|
||||||
|
|
||||||
// The time it takes for the floating cursor to snap to the text aligned
|
|
||||||
// cursor position after the user has finished placing it.
|
|
||||||
static const Duration _floatingCursorResetTime = Duration(milliseconds: 125);
|
|
||||||
|
|
||||||
AnimationController _floatingCursorResetController;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get wantKeepAlive => widget.focusNode.hasFocus;
|
bool get wantKeepAlive => widget.focusNode.hasFocus;
|
||||||
|
|
||||||
@ -530,8 +514,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
widget.controller.addListener(_didChangeTextEditingValue);
|
widget.controller.addListener(_didChangeTextEditingValue);
|
||||||
widget.focusNode.addListener(_handleFocusChanged);
|
widget.focusNode.addListener(_handleFocusChanged);
|
||||||
_scrollController.addListener(() { _selectionOverlay?.updateForScroll(); });
|
_scrollController.addListener(() { _selectionOverlay?.updateForScroll(); });
|
||||||
_floatingCursorResetController = AnimationController(vsync: this);
|
|
||||||
_floatingCursorResetController.addListener(_onFloatingCursorResetTick);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -613,72 +595,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The original position of the caret on FloatingCursorDragState.start.
|
|
||||||
Rect _startCaretRect;
|
|
||||||
|
|
||||||
// The most recent text position as determined by the location of the floating
|
|
||||||
// cursor.
|
|
||||||
TextPosition _lastTextPosition;
|
|
||||||
|
|
||||||
// The offset of the floating cursor as determined from the first update call.
|
|
||||||
Offset _pointOffsetOrigin;
|
|
||||||
|
|
||||||
// The most recent position of the floating cursor.
|
|
||||||
Offset _lastBoundedOffset;
|
|
||||||
|
|
||||||
// Because the center of the cursor is preferredLineHeight / 2 below the touch
|
|
||||||
// origin, but the touch origin is used to determine which line the cursor is
|
|
||||||
// on, we need this offset to correctly render and move the cursor.
|
|
||||||
Offset get _floatingCursorOffset => Offset(0, renderEditable.preferredLineHeight / 2);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void updateFloatingCursor(RawFloatingCursorPoint point) {
|
|
||||||
switch(point.state){
|
|
||||||
case FloatingCursorDragState.Start:
|
|
||||||
final TextPosition currentTextPosition = TextPosition(offset: renderEditable.selection.baseOffset);
|
|
||||||
_startCaretRect = renderEditable.getLocalRectForCaret(currentTextPosition);
|
|
||||||
renderEditable.setFloatingCursor(point.state, _startCaretRect.center - _floatingCursorOffset, currentTextPosition);
|
|
||||||
break;
|
|
||||||
case FloatingCursorDragState.Update:
|
|
||||||
// We want to send in points that are centered around a (0,0) origin, so we cache the
|
|
||||||
// position on the first update call.
|
|
||||||
if (_pointOffsetOrigin != null) {
|
|
||||||
final Offset centeredPoint = point.offset - _pointOffsetOrigin;
|
|
||||||
final Offset rawCursorOffset = _startCaretRect.center + centeredPoint - _floatingCursorOffset;
|
|
||||||
_lastBoundedOffset = renderEditable.calculateBoundedFloatingCursorOffset(rawCursorOffset);
|
|
||||||
_lastTextPosition = renderEditable.getPositionForPoint(renderEditable.localToGlobal(_lastBoundedOffset + _floatingCursorOffset));
|
|
||||||
renderEditable.setFloatingCursor(point.state, _lastBoundedOffset, _lastTextPosition);
|
|
||||||
} else {
|
|
||||||
_pointOffsetOrigin = point.offset;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FloatingCursorDragState.End:
|
|
||||||
_floatingCursorResetController.value = 0.0;
|
|
||||||
_floatingCursorResetController.animateTo(1.0, duration: _floatingCursorResetTime, curve: Curves.decelerate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onFloatingCursorResetTick() {
|
|
||||||
final Offset finalPosition = renderEditable.getLocalRectForCaret(_lastTextPosition).center - _floatingCursorOffset;
|
|
||||||
if (_floatingCursorResetController.isCompleted) {
|
|
||||||
renderEditable.setFloatingCursor(FloatingCursorDragState.End, finalPosition, _lastTextPosition);
|
|
||||||
if (_lastTextPosition.offset != renderEditable.selection.baseOffset)
|
|
||||||
// The cause is technically the force cursor, but the cause is listed as tap as the desired functionality is the same.
|
|
||||||
_handleSelectionChanged(TextSelection.collapsed(offset: _lastTextPosition.offset), renderEditable, SelectionChangedCause.tap);
|
|
||||||
_startCaretRect = null;
|
|
||||||
_lastTextPosition = null;
|
|
||||||
_pointOffsetOrigin = null;
|
|
||||||
_lastBoundedOffset = null;
|
|
||||||
} else {
|
|
||||||
final double lerpValue = _floatingCursorResetController.value;
|
|
||||||
final double lerpX = ui.lerpDouble(_lastBoundedOffset.dx, finalPosition.dx, lerpValue);
|
|
||||||
final double lerpY = ui.lerpDouble(_lastBoundedOffset.dy, finalPosition.dy, lerpValue);
|
|
||||||
|
|
||||||
renderEditable.setFloatingCursor(FloatingCursorDragState.Update, Offset(lerpX, lerpY), _lastTextPosition, resetLerpValue: lerpValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _finalizeEditing(bool shouldUnfocus) {
|
void _finalizeEditing(bool shouldUnfocus) {
|
||||||
// Take any actions necessary now that the user has completed editing.
|
// Take any actions necessary now that the user has completed editing.
|
||||||
if (widget.onEditingComplete != null) {
|
if (widget.onEditingComplete != null) {
|
||||||
@ -1053,7 +969,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
textSpan: buildTextSpan(),
|
textSpan: buildTextSpan(),
|
||||||
value: _value,
|
value: _value,
|
||||||
cursorColor: widget.cursorColor,
|
cursorColor: widget.cursorColor,
|
||||||
backgroundCursorColor: widget.backgroundCursorColor,
|
|
||||||
showCursor: EditableText.debugDeterministicCursor ? ValueNotifier<bool>(true) : _showCursor,
|
showCursor: EditableText.debugDeterministicCursor ? ValueNotifier<bool>(true) : _showCursor,
|
||||||
hasFocus: _hasFocus,
|
hasFocus: _hasFocus,
|
||||||
maxLines: widget.maxLines,
|
maxLines: widget.maxLines,
|
||||||
@ -1119,7 +1034,6 @@ class _Editable extends LeafRenderObjectWidget {
|
|||||||
this.textSpan,
|
this.textSpan,
|
||||||
this.value,
|
this.value,
|
||||||
this.cursorColor,
|
this.cursorColor,
|
||||||
this.backgroundCursorColor,
|
|
||||||
this.showCursor,
|
this.showCursor,
|
||||||
this.hasFocus,
|
this.hasFocus,
|
||||||
this.maxLines,
|
this.maxLines,
|
||||||
@ -1146,7 +1060,6 @@ class _Editable extends LeafRenderObjectWidget {
|
|||||||
final TextSpan textSpan;
|
final TextSpan textSpan;
|
||||||
final TextEditingValue value;
|
final TextEditingValue value;
|
||||||
final Color cursorColor;
|
final Color cursorColor;
|
||||||
final Color backgroundCursorColor;
|
|
||||||
final ValueNotifier<bool> showCursor;
|
final ValueNotifier<bool> showCursor;
|
||||||
final bool hasFocus;
|
final bool hasFocus;
|
||||||
final int maxLines;
|
final int maxLines;
|
||||||
@ -1171,7 +1084,6 @@ class _Editable extends LeafRenderObjectWidget {
|
|||||||
return RenderEditable(
|
return RenderEditable(
|
||||||
text: textSpan,
|
text: textSpan,
|
||||||
cursorColor: cursorColor,
|
cursorColor: cursorColor,
|
||||||
backgroundCursorColor: backgroundCursorColor,
|
|
||||||
showCursor: showCursor,
|
showCursor: showCursor,
|
||||||
hasFocus: hasFocus,
|
hasFocus: hasFocus,
|
||||||
maxLines: maxLines,
|
maxLines: maxLines,
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
|
|
||||||
import '../rendering/mock_canvas.dart';
|
import '../rendering/mock_canvas.dart';
|
||||||
import '../rendering/recording_canvas.dart';
|
import '../rendering/recording_canvas.dart';
|
||||||
@ -26,10 +24,6 @@ class FakeEditableTextState extends TextSelectionDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
final TextEditingController controller = TextEditingController();
|
|
||||||
const TextStyle textStyle = TextStyle();
|
|
||||||
|
|
||||||
test('editable intrinsics', () {
|
test('editable intrinsics', () {
|
||||||
final TextSelectionDelegate delegate = FakeEditableTextState();
|
final TextSelectionDelegate delegate = FakeEditableTextState();
|
||||||
final RenderEditable editable = RenderEditable(
|
final RenderEditable editable = RenderEditable(
|
||||||
@ -97,68 +91,4 @@ void main() {
|
|||||||
paints..clipRect(rect: Rect.fromLTRB(0.0, 0.0, 1000.0, 10.0))
|
paints..clipRect(rect: Rect.fromLTRB(0.0, 0.0, 1000.0, 10.0))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
RenderEditable findRenderEditable(WidgetTester tester) {
|
|
||||||
final RenderObject root = tester.renderObject(find.byType(EditableText));
|
|
||||||
expect(root, isNotNull);
|
|
||||||
|
|
||||||
RenderEditable renderEditable;
|
|
||||||
void recursiveFinder(RenderObject child) {
|
|
||||||
if (child is RenderEditable) {
|
|
||||||
renderEditable = child;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
child.visitChildren(recursiveFinder);
|
|
||||||
}
|
|
||||||
root.visitChildren(recursiveFinder);
|
|
||||||
expect(renderEditable, isNotNull);
|
|
||||||
return renderEditable;
|
|
||||||
}
|
|
||||||
|
|
||||||
testWidgets('Floating cursor is painted', (WidgetTester tester) async {
|
|
||||||
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
|
|
||||||
const String text = 'hello world this is fun and cool and awesome!';
|
|
||||||
controller.text = text;
|
|
||||||
final FocusNode focusNode = FocusNode();
|
|
||||||
|
|
||||||
await tester.pumpWidget(
|
|
||||||
MaterialApp(
|
|
||||||
home: Material(
|
|
||||||
child: TextField(
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
style: textStyle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await tester.tap(find.byType(EditableText));
|
|
||||||
final RenderEditable editable = findRenderEditable(tester);
|
|
||||||
editable.selection = const TextSelection(baseOffset: 29, extentOffset: 29);
|
|
||||||
|
|
||||||
final EditableTextState editableTextState = tester.firstState(find.byType(EditableText));
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start));
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(20, 20)));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
expect(find.byType(EditableText), paints..rrect(
|
|
||||||
rrect: RRect.fromRectAndRadius(Rect.fromLTRB(406.5, 0, 409.5, 14.0), const Radius.circular(1.0)), color: const Color(0xff4285f4))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Moves the cursor right a few characters.
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(-250, 20)));
|
|
||||||
|
|
||||||
expect(find.byType(EditableText), paints..rrect(
|
|
||||||
rrect: RRect.fromRectAndRadius(Rect.fromLTRB(136.5, 0, 139.5, 14.0), const Radius.circular(1.0)), color: const Color(0xff4285f4))
|
|
||||||
);
|
|
||||||
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End));
|
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
debugDefaultTargetPlatformOverride = null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -1024,49 +1024,16 @@ class _RectPaintPredicate extends _OneParameterPaintPredicate<Rect> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RRectPaintPredicate extends _DrawCommandPaintPredicate {
|
class _RRectPaintPredicate extends _OneParameterPaintPredicate<RRect> {
|
||||||
_RRectPaintPredicate({ this.rrect, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style }) : super(
|
_RRectPaintPredicate({ RRect rrect, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style }) : super(
|
||||||
#drawRRect,
|
#drawRRect,
|
||||||
'a rounded rectangle',
|
'a rounded rectangle',
|
||||||
2,
|
expected: rrect,
|
||||||
1,
|
|
||||||
color: color,
|
color: color,
|
||||||
strokeWidth: strokeWidth,
|
strokeWidth: strokeWidth,
|
||||||
hasMaskFilter: hasMaskFilter,
|
hasMaskFilter: hasMaskFilter,
|
||||||
style: style
|
style: style,
|
||||||
);
|
);
|
||||||
|
|
||||||
final RRect rrect;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void verifyArguments(List<dynamic> arguments) {
|
|
||||||
super.verifyArguments(arguments);
|
|
||||||
const double eps = .0001;
|
|
||||||
final RRect actual = arguments[0];
|
|
||||||
if (rrect != null &&
|
|
||||||
((actual.left - rrect.left).abs() > eps ||
|
|
||||||
(actual.right - rrect.right).abs() > eps ||
|
|
||||||
(actual.top - rrect.top).abs() > eps ||
|
|
||||||
(actual.bottom - rrect.bottom).abs() > eps ||
|
|
||||||
(actual.blRadiusX - rrect.blRadiusX).abs() > eps ||
|
|
||||||
(actual.blRadiusY - rrect.blRadiusY).abs() > eps ||
|
|
||||||
(actual.brRadiusX - rrect.brRadiusX).abs() > eps ||
|
|
||||||
(actual.brRadiusY - rrect.brRadiusY).abs() > eps ||
|
|
||||||
(actual.tlRadiusX - rrect.tlRadiusX).abs() > eps ||
|
|
||||||
(actual.tlRadiusY - rrect.tlRadiusY).abs() > eps ||
|
|
||||||
(actual.trRadiusX - rrect.trRadiusX).abs() > eps ||
|
|
||||||
(actual.trRadiusY - rrect.trRadiusY).abs() > eps)) {
|
|
||||||
throw 'It called $methodName with RRect, $actual, which was not exactly the expected RRect ($rrect).';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void debugFillDescription(List<String> description) {
|
|
||||||
super.debugFillDescription(description);
|
|
||||||
if (rrect != null) {
|
|
||||||
description.add('RRect: $rrect');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DRRectPaintPredicate extends _TwoParameterPaintPredicate<RRect, RRect> {
|
class _DRRectPaintPredicate extends _TwoParameterPaintPredicate<RRect, RRect> {
|
||||||
|
@ -26,7 +26,6 @@ void main() {
|
|||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
EditableText(
|
EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -68,7 +67,6 @@ void main() {
|
|||||||
height: 200.0,
|
height: 200.0,
|
||||||
),
|
),
|
||||||
EditableText(
|
EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
scrollPadding: const EdgeInsets.all(50.0),
|
scrollPadding: const EdgeInsets.all(50.0),
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -114,7 +112,6 @@ void main() {
|
|||||||
height: 350.0,
|
height: 350.0,
|
||||||
),
|
),
|
||||||
EditableText(
|
EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -164,7 +161,6 @@ void main() {
|
|||||||
height: 350.0,
|
height: 350.0,
|
||||||
),
|
),
|
||||||
EditableText(
|
EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -251,7 +247,6 @@ void main() {
|
|||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
EditableText(
|
EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
maxLines: null, // multi-line
|
maxLines: null, // multi-line
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -307,7 +302,6 @@ void main() {
|
|||||||
height: 200.0,
|
height: 200.0,
|
||||||
),
|
),
|
||||||
EditableText(
|
EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
scrollPadding: const EdgeInsets.only(bottom: 300.0),
|
scrollPadding: const EdgeInsets.only(bottom: 300.0),
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
@ -42,7 +42,6 @@ void main() {
|
|||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
textInputAction: action,
|
textInputAction: action,
|
||||||
@ -68,7 +67,6 @@ void main() {
|
|||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
cursorColor: cursorColor,
|
cursorColor: cursorColor,
|
||||||
@ -89,7 +87,6 @@ void main() {
|
|||||||
await tester.pumpWidget(Directionality(
|
await tester.pumpWidget(Directionality(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -114,7 +111,6 @@ void main() {
|
|||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
cursorColor: cursorColor,
|
cursorColor: cursorColor,
|
||||||
@ -276,7 +272,6 @@ void main() {
|
|||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -306,7 +301,6 @@ void main() {
|
|||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -335,7 +329,6 @@ void main() {
|
|||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
@ -368,7 +361,6 @@ void main() {
|
|||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
keyboardType: TextInputType.phone,
|
keyboardType: TextInputType.phone,
|
||||||
@ -400,7 +392,6 @@ void main() {
|
|||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
maxLines: 3, // Sets multiline keyboard implicitly.
|
maxLines: 3, // Sets multiline keyboard implicitly.
|
||||||
@ -431,7 +422,6 @@ void main() {
|
|||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
maxLines: 1, // Sets text keyboard implicitly.
|
maxLines: 1, // Sets text keyboard implicitly.
|
||||||
@ -461,7 +451,6 @@ void main() {
|
|||||||
String changedValue;
|
String changedValue;
|
||||||
final Widget widget = MaterialApp(
|
final Widget widget = MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
@ -505,7 +494,6 @@ void main() {
|
|||||||
home: RepaintBoundary(
|
home: RepaintBoundary(
|
||||||
key: const ValueKey<int>(1),
|
key: const ValueKey<int>(1),
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
@ -556,7 +544,6 @@ void main() {
|
|||||||
home: RepaintBoundary(
|
home: RepaintBoundary(
|
||||||
key: const ValueKey<int>(1),
|
key: const ValueKey<int>(1),
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
@ -607,7 +594,6 @@ void main() {
|
|||||||
|
|
||||||
final Widget widget = MaterialApp(
|
final Widget widget = MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -642,7 +628,6 @@ void main() {
|
|||||||
|
|
||||||
final Widget widget = MaterialApp(
|
final Widget widget = MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -684,7 +669,6 @@ void main() {
|
|||||||
|
|
||||||
final Widget widget = MaterialApp(
|
final Widget widget = MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -729,7 +713,6 @@ void main() {
|
|||||||
|
|
||||||
final Widget widget = MaterialApp(
|
final Widget widget = MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -774,7 +757,6 @@ void main() {
|
|||||||
|
|
||||||
final Widget widget = MaterialApp(
|
final Widget widget = MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -819,7 +801,6 @@ testWidgets(
|
|||||||
|
|
||||||
final Widget widget = MaterialApp(
|
final Widget widget = MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -872,7 +853,6 @@ testWidgets(
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Material(
|
child: Material(
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
key: editableTextKey,
|
key: editableTextKey,
|
||||||
controller: currentController,
|
controller: currentController,
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
@ -932,7 +912,6 @@ testWidgets(
|
|||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -973,7 +952,6 @@ testWidgets(
|
|||||||
child: FocusScope(
|
child: FocusScope(
|
||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -1014,7 +992,6 @@ testWidgets(
|
|||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
selectionControls: materialTextSelectionControls,
|
selectionControls: materialTextSelectionControls,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -1057,7 +1034,6 @@ testWidgets(
|
|||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -1133,7 +1109,6 @@ testWidgets(
|
|||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -1223,7 +1198,6 @@ testWidgets(
|
|||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -1323,7 +1297,6 @@ testWidgets(
|
|||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -1422,7 +1395,6 @@ testWidgets(
|
|||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -1518,7 +1490,6 @@ testWidgets(
|
|||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -1565,7 +1536,6 @@ testWidgets(
|
|||||||
MockTextSelectionControls controls, WidgetTester tester) {
|
MockTextSelectionControls controls, WidgetTester tester) {
|
||||||
return tester.pumpWidget(MaterialApp(
|
return tester.pumpWidget(MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
@ -1773,7 +1743,6 @@ testWidgets(
|
|||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: EditableText(
|
child: EditableText(
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
@ -1787,157 +1756,6 @@ testWidgets(
|
|||||||
expect(controller.selection.isCollapsed, true);
|
expect(controller.selection.isCollapsed, true);
|
||||||
expect(controller.selection.baseOffset, text.length);
|
expect(controller.selection.baseOffset, text.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
RenderEditable findRenderEditable(WidgetTester tester) {
|
|
||||||
final RenderObject root = tester.renderObject(find.byType(EditableText));
|
|
||||||
expect(root, isNotNull);
|
|
||||||
|
|
||||||
RenderEditable renderEditable;
|
|
||||||
void recursiveFinder(RenderObject child) {
|
|
||||||
if (child is RenderEditable) {
|
|
||||||
renderEditable = child;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
child.visitChildren(recursiveFinder);
|
|
||||||
}
|
|
||||||
root.visitChildren(recursiveFinder);
|
|
||||||
expect(renderEditable, isNotNull);
|
|
||||||
return renderEditable;
|
|
||||||
}
|
|
||||||
|
|
||||||
testWidgets('Updating the floating cursor correctly moves the cursor', (WidgetTester tester) async {
|
|
||||||
const String text = 'hello world this is fun and cool and awesome!';
|
|
||||||
controller.text = text;
|
|
||||||
final FocusNode focusNode = FocusNode();
|
|
||||||
|
|
||||||
await tester.pumpWidget(
|
|
||||||
Directionality(
|
|
||||||
textDirection: TextDirection.ltr,
|
|
||||||
child: FocusScope(
|
|
||||||
node: focusScopeNode,
|
|
||||||
autofocus: true,
|
|
||||||
child: EditableText(
|
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
style: textStyle,
|
|
||||||
cursorColor: cursorColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await tester.tap(find.byType(EditableText));
|
|
||||||
final RenderEditable renderEditable = findRenderEditable(tester);
|
|
||||||
renderEditable.selection = const TextSelection(baseOffset: 29, extentOffset: 29);
|
|
||||||
|
|
||||||
expect(controller.selection.baseOffset, 29);
|
|
||||||
|
|
||||||
final EditableTextState editableTextState = tester.firstState(find.byType(EditableText));
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start));
|
|
||||||
|
|
||||||
expect(controller.selection.baseOffset, 29);
|
|
||||||
|
|
||||||
// Sets the origin.
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(20, 20)));
|
|
||||||
|
|
||||||
expect(controller.selection.baseOffset, 29);
|
|
||||||
|
|
||||||
// Moves the cursor right a few characters.
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(-250, 20)));
|
|
||||||
|
|
||||||
// But we have not yet set the offset because the user is not done placing the cursor.
|
|
||||||
expect(controller.selection.baseOffset, 29);
|
|
||||||
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End));
|
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
// The cursor has been set.
|
|
||||||
expect(controller.selection.baseOffset, 10);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Cursor gets placed correctly after going out of bounds', (WidgetTester tester) async {
|
|
||||||
const String text = 'hello world this is fun and cool and awesome!';
|
|
||||||
controller.text = text;
|
|
||||||
final FocusNode focusNode = FocusNode();
|
|
||||||
|
|
||||||
await tester.pumpWidget(
|
|
||||||
Directionality(
|
|
||||||
textDirection: TextDirection.ltr,
|
|
||||||
child: FocusScope(
|
|
||||||
node: focusScopeNode,
|
|
||||||
autofocus: true,
|
|
||||||
child: EditableText(
|
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
style: textStyle,
|
|
||||||
cursorColor: cursorColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await tester.tap(find.byType(EditableText));
|
|
||||||
final RenderEditable renderEditable = findRenderEditable(tester);
|
|
||||||
renderEditable.selection = const TextSelection(baseOffset: 29, extentOffset: 29);
|
|
||||||
|
|
||||||
expect(controller.selection.baseOffset, 29);
|
|
||||||
|
|
||||||
final EditableTextState editableTextState = tester.firstState(find.byType(EditableText));
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start));
|
|
||||||
|
|
||||||
expect(controller.selection.baseOffset, 29);
|
|
||||||
|
|
||||||
// Sets the origin.
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(20, 20)));
|
|
||||||
|
|
||||||
expect(controller.selection.baseOffset, 29);
|
|
||||||
|
|
||||||
// Moves the cursor super far right
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(2090, 20)));
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(2100, 20)));
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(2090, 20)));
|
|
||||||
|
|
||||||
// After peaking the cursor, we move in the opposite direction.
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(1400, 20)));
|
|
||||||
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End));
|
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
// The cursor has been set.
|
|
||||||
expect(controller.selection.baseOffset, 8);
|
|
||||||
|
|
||||||
// Go in the other direction.
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start));
|
|
||||||
// Sets the origin.
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(20, 20)));
|
|
||||||
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(-5000, 20)));
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(-5010, 20)));
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(-5000, 20)));
|
|
||||||
|
|
||||||
// Move back in the opposite direction only a few hundred.
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
|
|
||||||
offset: const Offset(-4850, 20)));
|
|
||||||
|
|
||||||
editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End));
|
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
expect(controller.selection.baseOffset, 11);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockTextSelectionControls extends Mock implements TextSelectionControls {}
|
class MockTextSelectionControls extends Mock implements TextSelectionControls {}
|
||||||
@ -1951,7 +1769,6 @@ class CustomStyleEditableText extends EditableText {
|
|||||||
}) : super(
|
}) : super(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
cursorColor: cursorColor,
|
cursorColor: cursorColor,
|
||||||
backgroundCursorColor: Colors.grey,
|
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: style,
|
style: style,
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user