onTapDown method
- TapDragDownDetails details
Handler for TextSelectionGestureDetector.onTapDown.
By default, it forwards the tap to RenderEditable.handleTapDown and sets shouldShowSelectionToolbar to true if the tap was initiated by a finger or stylus.
See also:
- TextSelectionGestureDetector.onTapDown, which triggers this callback.
Implementation
@protected
void onTapDown(TapDragDownDetails details) {
if (!delegate.selectionEnabled) {
return;
}
// TODO(Renzo-Olivares): Migrate text selection gestures away from saving state
// in renderEditable. The gesture callbacks can use the details objects directly
// in callbacks variants that provide them [TapGestureRecognizer.onSecondaryTap]
// vs [TapGestureRecognizer.onSecondaryTapUp] instead of having to track state in
// renderEditable. When this migration is complete we should remove this hack.
// See https://github.com/flutter/flutter/issues/115130.
renderEditable.handleTapDown(TapDownDetails(globalPosition: details.globalPosition));
// The selection overlay should only be shown when the user is interacting
// through a touch screen (via either a finger or a stylus). A mouse shouldn't
// trigger the selection overlay.
// For backwards-compatibility, we treat a null kind the same as touch.
final PointerDeviceKind? kind = details.kind;
// TODO(justinmc): Should a desktop platform show its selection toolbar when
// receiving a tap event? Say a Windows device with a touchscreen.
// https://github.com/flutter/flutter/issues/106586
_shouldShowSelectionToolbar =
kind == null || kind == PointerDeviceKind.touch || kind == PointerDeviceKind.stylus;
// It is impossible to extend the selection when the shift key is pressed, if the
// renderEditable.selection is invalid.
final bool isShiftPressedValid =
_isShiftPressed && renderEditable.selection?.baseOffset != null;
switch (defaultTargetPlatform) {
case TargetPlatform.android:
if (editableText.widget.stylusHandwritingEnabled) {
final bool stylusEnabled = switch (kind) {
PointerDeviceKind.stylus ||
PointerDeviceKind.invertedStylus => editableText.widget.stylusHandwritingEnabled,
_ => false,
};
if (stylusEnabled) {
Scribe.isFeatureAvailable().then((bool isAvailable) {
if (isAvailable) {
renderEditable.selectPosition(cause: SelectionChangedCause.scribble);
Scribe.startStylusHandwriting();
}
});
}
}
case TargetPlatform.fuchsia:
case TargetPlatform.iOS:
// On mobile platforms the selection is set on tap up.
break;
case TargetPlatform.macOS:
editableText.hideToolbar();
// On macOS, a shift-tapped unfocused field expands from 0, not from the
// previous selection.
if (isShiftPressedValid) {
final TextSelection? fromSelection =
renderEditable.hasFocus ? null : const TextSelection.collapsed(offset: 0);
_expandSelection(details.globalPosition, SelectionChangedCause.tap, fromSelection);
return;
}
// On macOS, a tap/click places the selection in a precise position.
// This differs from iOS/iPadOS, where if the gesture is done by a touch
// then the selection moves to the closest word edge, instead of a
// precise position.
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
case TargetPlatform.linux:
case TargetPlatform.windows:
editableText.hideToolbar();
if (isShiftPressedValid) {
_extendSelection(details.globalPosition, SelectionChangedCause.tap);
return;
}
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
}
}