onDragSelectionUpdate method
- TapDragUpdateDetails details
Handler for TextSelectionGestureDetector.onDragSelectionUpdate.
By default, it updates the selection location specified in the provided details objects.
See also:
- TextSelectionGestureDetector.onDragSelectionUpdate, which triggers this callback./lib/src/material/text_field.dart
Implementation
@protected
void onDragSelectionUpdate(TapDragUpdateDetails details) {
if (!delegate.selectionEnabled) {
return;
}
if (!_isShiftPressed) {
// Adjust the drag start offset for possible viewport offset changes.
final Offset editableOffset = renderEditable.maxLines == 1
? Offset(renderEditable.offset.pixels - _dragStartViewportOffset, 0.0)
: Offset(0.0, renderEditable.offset.pixels - _dragStartViewportOffset);
final Offset scrollableOffset = switch (axisDirectionToAxis(_scrollDirection ?? AxisDirection.left)) {
Axis.horizontal => Offset(_scrollPosition - _dragStartScrollOffset, 0.0),
Axis.vertical => Offset(0.0, _scrollPosition - _dragStartScrollOffset),
};
final Offset dragStartGlobalPosition = details.globalPosition - details.offsetFromOrigin;
// Select word by word.
if (_TextSelectionGestureDetectorState._getEffectiveConsecutiveTapCount(details.consecutiveTapCount) == 2) {
renderEditable.selectWordsInRange(
from: dragStartGlobalPosition - editableOffset - scrollableOffset,
to: details.globalPosition,
cause: SelectionChangedCause.drag,
);
switch (details.kind) {
case PointerDeviceKind.stylus:
case PointerDeviceKind.invertedStylus:
case PointerDeviceKind.touch:
case PointerDeviceKind.unknown:
return _showMagnifierIfSupportedByPlatform(details.globalPosition);
case PointerDeviceKind.mouse:
case PointerDeviceKind.trackpad:
case null:
return;
}
}
// Select paragraph-by-paragraph.
if (_TextSelectionGestureDetectorState._getEffectiveConsecutiveTapCount(details.consecutiveTapCount) == 3) {
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.iOS:
switch (details.kind) {
case PointerDeviceKind.mouse:
case PointerDeviceKind.trackpad:
return _selectParagraphsInRange(
from: dragStartGlobalPosition - editableOffset - scrollableOffset,
to: details.globalPosition,
cause: SelectionChangedCause.drag,
);
case PointerDeviceKind.stylus:
case PointerDeviceKind.invertedStylus:
case PointerDeviceKind.touch:
case PointerDeviceKind.unknown:
case null:
// Triple tap to drag is not present on these platforms when using
// non-precise pointer devices at the moment.
break;
}
return;
case TargetPlatform.linux:
return _selectLinesInRange(
from: dragStartGlobalPosition - editableOffset - scrollableOffset,
to: details.globalPosition,
cause: SelectionChangedCause.drag,
);
case TargetPlatform.windows:
case TargetPlatform.macOS:
return _selectParagraphsInRange(
from: dragStartGlobalPosition - editableOffset - scrollableOffset,
to: details.globalPosition,
cause: SelectionChangedCause.drag,
);
}
}
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
// With a mouse device, a drag should select the range from the origin of the drag
// to the current position of the drag.
//
// With a touch device, nothing should happen.
switch (details.kind) {
case PointerDeviceKind.mouse:
case PointerDeviceKind.trackpad:
return renderEditable.selectPositionAt(
from: dragStartGlobalPosition - editableOffset - scrollableOffset,
to: details.globalPosition,
cause: SelectionChangedCause.drag,
);
case PointerDeviceKind.stylus:
case PointerDeviceKind.invertedStylus:
case PointerDeviceKind.touch:
case PointerDeviceKind.unknown:
case null:
break;
}
return;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
// With a precise pointer device, such as a mouse, trackpad, or stylus,
// the drag will select the text spanning the origin of the drag to the end of the drag.
// With a touch device, the cursor should move with the drag.
switch (details.kind) {
case PointerDeviceKind.mouse:
case PointerDeviceKind.trackpad:
case PointerDeviceKind.stylus:
case PointerDeviceKind.invertedStylus:
return renderEditable.selectPositionAt(
from: dragStartGlobalPosition - editableOffset - scrollableOffset,
to: details.globalPosition,
cause: SelectionChangedCause.drag,
);
case PointerDeviceKind.touch:
case PointerDeviceKind.unknown:
if (renderEditable.hasFocus) {
renderEditable.selectPositionAt(
from: details.globalPosition,
cause: SelectionChangedCause.drag,
);
return _showMagnifierIfSupportedByPlatform(details.globalPosition);
}
case null:
break;
}
return;
case TargetPlatform.macOS:
case TargetPlatform.linux:
case TargetPlatform.windows:
return renderEditable.selectPositionAt(
from: dragStartGlobalPosition - editableOffset - scrollableOffset,
to: details.globalPosition,
cause: SelectionChangedCause.drag,
);
}
}
if (_dragStartSelection!.isCollapsed
|| (defaultTargetPlatform != TargetPlatform.iOS
&& defaultTargetPlatform != TargetPlatform.macOS)) {
return _extendSelection(details.globalPosition, SelectionChangedCause.drag);
}
// If the drag inverts the selection, Mac and iOS revert to the initial
// selection.
final TextSelection selection = editableText.textEditingValue.selection;
final TextPosition nextExtent = renderEditable.getPositionForPoint(details.globalPosition);
final bool isShiftTapDragSelectionForward =
_dragStartSelection!.baseOffset < _dragStartSelection!.extentOffset;
final bool isInverted = isShiftTapDragSelectionForward
? nextExtent.offset < _dragStartSelection!.baseOffset
: nextExtent.offset > _dragStartSelection!.baseOffset;
if (isInverted && selection.baseOffset == _dragStartSelection!.baseOffset) {
editableText.userUpdateTextEditingValue(
editableText.textEditingValue.copyWith(
selection: TextSelection(
baseOffset: _dragStartSelection!.extentOffset,
extentOffset: nextExtent.offset,
),
),
SelectionChangedCause.drag,
);
} else if (!isInverted
&& nextExtent.offset != _dragStartSelection!.baseOffset
&& selection.baseOffset != _dragStartSelection!.baseOffset) {
editableText.userUpdateTextEditingValue(
editableText.textEditingValue.copyWith(
selection: TextSelection(
baseOffset: _dragStartSelection!.baseOffset,
extentOffset: nextExtent.offset,
),
),
SelectionChangedCause.drag,
);
} else {
_extendSelection(details.globalPosition, SelectionChangedCause.drag);
}
}