Skip to content

Commit

Permalink
User ScrollPosition.drag to perform scrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
angelosilvestre committed Oct 24, 2023
1 parent dde32c8 commit 53b0967
Show file tree
Hide file tree
Showing 6 changed files with 485 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ class _AndroidDocumentTouchInteractorState extends State<AndroidDocumentTouchInt
AndroidDocumentLongPressSelectionStrategy? _longPressStrategy;
final _longPressMagnifierGlobalOffset = ValueNotifier<Offset?>(null);

/// Holds the drag gesture that scrolls the document.
Drag? _drag;

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -742,6 +745,11 @@ class _AndroidDocumentTouchInteractorState extends State<AndroidDocumentTouchInt

if (!_isLongPressInProgress) {
// We only care about starting a pan if we're long-press dragging.
_drag = scrollPosition.drag(details, () {
// Allows receiving touches while scrolling due to scroll momentum.
// This is needed to allow the user to stop scrolling by tapping down.
scrollPosition.context.setIgnorePointer(false);
});
return;
}

Expand Down Expand Up @@ -786,8 +794,10 @@ class _AndroidDocumentTouchInteractorState extends State<AndroidDocumentTouchInt
return;
}

// The user is trying to scroll the document. Change the scroll offset.
scrollPosition.pointerScroll(-details.delta.dy);
if (_drag != null) {
// The user is trying to scroll the document. Change the scroll offset.
_drag!.update(details);
}
}

void _updateLongPressSelection(DocumentSelection newSelection) {
Expand Down Expand Up @@ -818,6 +828,10 @@ class _AndroidDocumentTouchInteractorState extends State<AndroidDocumentTouchInt
return;
}

if (_drag != null) {
_drag!.end(details);
}

final pos = scrollPosition;
if (pos is ScrollPositionWithSingleContext) {
pos.goBallistic(-details.velocity.pixelsPerSecond.dy);
Expand All @@ -830,6 +844,10 @@ class _AndroidDocumentTouchInteractorState extends State<AndroidDocumentTouchInt
_onLongPressEnd();
return;
}

if (_drag != null) {
_drag!.cancel();
}
}

void _onLongPressEnd() {
Expand Down Expand Up @@ -1252,10 +1270,11 @@ class _AndroidDocumentTouchInteractorState extends State<AndroidDocumentTouchInt
..gestureSettings = gestureSettings;
},
),
PanGestureRecognizer: GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
() => PanGestureRecognizer(),
(PanGestureRecognizer recognizer) {
VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer(),
(VerticalDragGestureRecognizer recognizer) {
recognizer
..dragStartBehavior = DragStartBehavior.down
..onStart = _onPanStart
..onUpdate = _onPanUpdate
..onEnd = _onPanEnd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ class _IOSDocumentTouchInteractorState extends State<IOSDocumentTouchInteractor>
bool get _isLongPressInProgress => _longPressStrategy != null;
IosLongPressSelectionStrategy? _longPressStrategy;

/// Holds the drag gesture that scrolls the document.
Drag? _drag;

// Whether we're currently waiting to see if the user taps
// again on the document.
//
Expand Down Expand Up @@ -788,15 +791,12 @@ class _IOSDocumentTouchInteractorState extends State<IOSDocumentTouchInteractor>
// placement during onTapDown, and then pick that up here. I think the little
// bit of slop might be the problem.
final selection = widget.selection.value;
if (selection == null) {
return;
}

if (_isLongPressInProgress) {
_dragMode = DragMode.longPress;
_dragHandleType = null;
_longPressStrategy!.onLongPressDragStart();
} else if (selection.isCollapsed && _isOverCollapsedHandle(details.localPosition)) {
} else if (selection != null && selection.isCollapsed && _isOverCollapsedHandle(details.localPosition)) {
_dragMode = DragMode.collapsed;
_dragHandleType = HandleType.collapsed;
} else if (_isOverBaseHandle(details.localPosition)) {
Expand All @@ -806,6 +806,15 @@ class _IOSDocumentTouchInteractorState extends State<IOSDocumentTouchInteractor>
_dragMode = DragMode.extent;
_dragHandleType = HandleType.downstream;
} else {
_drag = scrollPosition.drag(details, () {
// Allows receiving touches while scrolling due to scroll momentum.
// This is needed to allow the user to stop scrolling by tapping down.
scrollPosition.context.setIgnorePointer(false);
});
return;
}

if (selection == null) {
return;
}

Expand Down Expand Up @@ -890,8 +899,8 @@ class _IOSDocumentTouchInteractorState extends State<IOSDocumentTouchInteractor>
void _onPanUpdate(DragUpdateDetails details) {
// If the user isn't dragging a handle, then the user is trying to
// scroll the document. Scroll it, accordingly.
if (_dragMode == null) {
scrollPosition.jumpTo(scrollPosition.pixels - details.delta.dy);
if (_dragMode == null && _drag != null) {
_drag!.update(details);
_positionToolbar();
return;
}
Expand Down Expand Up @@ -966,6 +975,13 @@ class _IOSDocumentTouchInteractorState extends State<IOSDocumentTouchInteractor>
}

void _onPanEnd(DragEndDetails details) {
if (_drag != null) {
_drag!.end(details);
_drag = null;

return;
}

if (_dragMode == null) {
// User was dragging the scroll area. Go ballistic.
if (scrollPosition is ScrollPositionWithSingleContext) {
Expand All @@ -987,6 +1003,11 @@ class _IOSDocumentTouchInteractorState extends State<IOSDocumentTouchInteractor>
}

void _onPanCancel() {
if (_drag != null) {
_drag!.cancel();
_drag = null;
}

if (_dragMode != null) {
_onDragSelectionEnd();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ class _ReadOnlyAndroidDocumentTouchInteractorState extends State<ReadOnlyAndroid
AndroidDocumentLongPressSelectionStrategy? _longPressStrategy;
final _longPressMagnifierGlobalOffset = ValueNotifier<Offset?>(null);

/// Holds the drag gesture that scrolls the document.
Drag? _drag;

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -668,6 +671,11 @@ class _ReadOnlyAndroidDocumentTouchInteractorState extends State<ReadOnlyAndroid

if (!_isLongPressInProgress) {
// We only care about starting a pan if we're long-press dragging.
_drag = scrollPosition.drag(details, () {
// Allows receiving touches while scrolling due to scroll momentum.
// This is needed to allow the user to stop scrolling by tapping down.
scrollPosition.context.setIgnorePointer(false);
});
return;
}

Expand Down Expand Up @@ -712,7 +720,10 @@ class _ReadOnlyAndroidDocumentTouchInteractorState extends State<ReadOnlyAndroid
return;
}

scrollPosition.pointerScroll(-details.delta.dy);
if (_drag != null) {
// The user is trying to scroll the document. Change the scroll offset.
_drag!.update(details);
}
}

void _updateLongPressSelection(DocumentSelection newSelection) {
Expand Down Expand Up @@ -743,6 +754,10 @@ class _ReadOnlyAndroidDocumentTouchInteractorState extends State<ReadOnlyAndroid
return;
}

if (_drag != null) {
_drag!.end(details);
}

final pos = scrollPosition;
if (pos is ScrollPositionWithSingleContext) {
pos.goBallistic(-details.velocity.pixelsPerSecond.dy);
Expand All @@ -755,6 +770,10 @@ class _ReadOnlyAndroidDocumentTouchInteractorState extends State<ReadOnlyAndroid
_onLongPressEnd();
return;
}

if (_drag != null) {
_drag!.cancel();
}
}

void _onLongPressEnd() {
Expand Down Expand Up @@ -1036,10 +1055,11 @@ class _ReadOnlyAndroidDocumentTouchInteractorState extends State<ReadOnlyAndroid
..gestureSettings = gestureSettings;
},
),
PanGestureRecognizer: GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
() => PanGestureRecognizer(),
(PanGestureRecognizer recognizer) {
VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer(),
(VerticalDragGestureRecognizer recognizer) {
recognizer
..dragStartBehavior = DragStartBehavior.down
..onStart = _onPanStart
..onUpdate = _onPanUpdate
..onEnd = _onPanEnd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ class _ReadOnlyIOSDocumentTouchInteractorState extends State<ReadOnlyIOSDocument
/// Shows, hides, and positions a floating toolbar and magnifier.
late MagnifierAndToolbarController _overlayController;

/// Holds the drag gesture that scrolls the document.
Drag? _drag;

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -635,21 +638,27 @@ class _ReadOnlyIOSDocumentTouchInteractorState extends State<ReadOnlyIOSDocument
// placement during onTapDown, and then pick that up here. I think the little
// bit of slop might be the problem.
final selection = widget.selection.value;
if (selection == null) {
return;
}

if (_isLongPressInProgress) {
_dragMode = DragMode.longPress;
_dragHandleType = null;
_longPressStrategy!.onLongPressDragStart();
} else if (_isOverBaseHandle(details.localPosition)) {
} else if (selection != null && _isOverBaseHandle(details.localPosition)) {
_dragMode = DragMode.base;
_dragHandleType = HandleType.upstream;
} else if (_isOverExtentHandle(details.localPosition)) {
} else if (selection != null && _isOverExtentHandle(details.localPosition)) {
_dragMode = DragMode.extent;
_dragHandleType = HandleType.downstream;
} else {
_drag = scrollPosition.drag(details, () {
// Allows receiving touches while scrolling due to scroll momentum.
// This is needed to allow the user to stop scrolling by tapping down.
scrollPosition.context.setIgnorePointer(false);
});
return;
}

if (selection == null) {
return;
}

Expand Down Expand Up @@ -721,8 +730,8 @@ class _ReadOnlyIOSDocumentTouchInteractorState extends State<ReadOnlyIOSDocument
void _onPanUpdate(DragUpdateDetails details) {
// If the user isn't dragging a handle, then the user is trying to
// scroll the document. Scroll it, accordingly.
if (_dragMode == null) {
scrollPosition.jumpTo(scrollPosition.pixels - details.delta.dy);
if (_dragMode == null && _drag != null) {
_drag!.update(details);
_positionToolbar();
return;
}
Expand Down Expand Up @@ -777,6 +786,13 @@ class _ReadOnlyIOSDocumentTouchInteractorState extends State<ReadOnlyIOSDocument
}

void _onPanEnd(DragEndDetails details) {
if (_drag != null) {
_drag!.end(details);
_drag = null;

return;
}

if (_dragMode == null) {
// User was dragging the scroll area. Go ballistic.
if (scrollPosition is ScrollPositionWithSingleContext) {
Expand All @@ -798,6 +814,11 @@ class _ReadOnlyIOSDocumentTouchInteractorState extends State<ReadOnlyIOSDocument
}

void _onPanCancel() {
if (_drag != null) {
_drag!.cancel();
_drag = null;
}

if (_dragMode != null) {
_onDragSelectionEnd();
}
Expand Down
Loading

0 comments on commit 53b0967

Please sign in to comment.