feat: add animation during auto scrolling (#1153)
This commit is contained in:
parent
387a90ce39
commit
5c4a6f904c
5 changed files with 37 additions and 9 deletions
|
|
@ -20,6 +20,7 @@ class AutoScroller extends EdgeDraggingAutoScroller
|
||||||
super.velocityScalar = _kDefaultAutoScrollVelocityScalar,
|
super.velocityScalar = _kDefaultAutoScrollVelocityScalar,
|
||||||
super.minimumAutoScrollDelta = _kDefaultMinAutoScrollDelta,
|
super.minimumAutoScrollDelta = _kDefaultMinAutoScrollDelta,
|
||||||
super.maxAutoScrollDelta = _kDefaultMaxAutoScrollDelta,
|
super.maxAutoScrollDelta = _kDefaultMaxAutoScrollDelta,
|
||||||
|
super.animationDuration,
|
||||||
});
|
});
|
||||||
|
|
||||||
static const double _kDefaultAutoScrollVelocityScalar = 7;
|
static const double _kDefaultAutoScrollVelocityScalar = 7;
|
||||||
|
|
@ -28,6 +29,8 @@ class AutoScroller extends EdgeDraggingAutoScroller
|
||||||
|
|
||||||
Offset? lastOffset;
|
Offset? lastOffset;
|
||||||
Duration? lastDuration;
|
Duration? lastDuration;
|
||||||
|
double? lastEdgeOffset;
|
||||||
|
AxisDirection? lastDirection;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void startAutoScroll(
|
void startAutoScroll(
|
||||||
|
|
@ -38,9 +41,12 @@ class AutoScroller extends EdgeDraggingAutoScroller
|
||||||
}) {
|
}) {
|
||||||
lastOffset = offset;
|
lastOffset = offset;
|
||||||
lastDuration = duration;
|
lastDuration = duration;
|
||||||
|
lastEdgeOffset = edgeOffset;
|
||||||
|
lastDirection = direction;
|
||||||
if (direction != null && direction == AxisDirection.up) {
|
if (direction != null && direction == AxisDirection.up) {
|
||||||
return startAutoScrollIfNecessary(
|
return startAutoScrollIfNecessary(
|
||||||
offset & Size(1, edgeOffset),
|
offset & Size(1, edgeOffset),
|
||||||
|
duration: duration,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,6 +58,7 @@ class AutoScroller extends EdgeDraggingAutoScroller
|
||||||
|
|
||||||
startAutoScrollIfNecessary(
|
startAutoScrollIfNecessary(
|
||||||
dragTarget,
|
dragTarget,
|
||||||
|
duration: duration,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,6 +66,8 @@ class AutoScroller extends EdgeDraggingAutoScroller
|
||||||
void stopAutoScroll() {
|
void stopAutoScroll() {
|
||||||
lastOffset = null;
|
lastOffset = null;
|
||||||
lastDuration = null;
|
lastDuration = null;
|
||||||
|
lastEdgeOffset = null;
|
||||||
|
lastDirection = null;
|
||||||
super.stopAutoScroll();
|
super.stopAutoScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,6 +75,8 @@ class AutoScroller extends EdgeDraggingAutoScroller
|
||||||
if (lastOffset != null) {
|
if (lastOffset != null) {
|
||||||
startAutoScroll(
|
startAutoScroll(
|
||||||
lastOffset!,
|
lastOffset!,
|
||||||
|
edgeOffset: lastEdgeOffset ?? 200,
|
||||||
|
direction: lastDirection,
|
||||||
duration: lastDuration,
|
duration: lastDuration,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,14 @@ class _ScrollServiceWidgetState extends State<ScrollServiceWidget>
|
||||||
AxisDirection? direction;
|
AxisDirection? direction;
|
||||||
final dynamic dragMode =
|
final dynamic dragMode =
|
||||||
editorState.selectionExtraInfo?['selection_drag_mode'];
|
editorState.selectionExtraInfo?['selection_drag_mode'];
|
||||||
|
|
||||||
|
// For desktop: if auto-scroller is already scrolling (from drag-to-select),
|
||||||
|
// don't override it here. The desktop_selection_service handles drag scrolling.
|
||||||
|
if (PlatformExtension.isDesktopOrWeb &&
|
||||||
|
(editorState.autoScroller?.scrolling ?? false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (dragMode?.toString()) {
|
switch (dragMode?.toString()) {
|
||||||
case 'MobileSelectionDragMode.leftSelectionHandle':
|
case 'MobileSelectionDragMode.leftSelectionHandle':
|
||||||
targetRect = selectionRects.first;
|
targetRect = selectionRects.first;
|
||||||
|
|
|
||||||
|
|
@ -345,7 +345,8 @@ class _DesktopSelectionServiceWidgetState
|
||||||
|
|
||||||
editorState.service.scrollService?.startAutoScroll(
|
editorState.service.scrollService?.startAutoScroll(
|
||||||
_lastPanOffset!,
|
_lastPanOffset!,
|
||||||
edgeOffset: 80,
|
edgeOffset: 200,
|
||||||
|
duration: const Duration(milliseconds: 2),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -636,9 +636,10 @@ class EditorState {
|
||||||
late AutoScroller scroller;
|
late AutoScroller scroller;
|
||||||
scroller = AutoScroller(
|
scroller = AutoScroller(
|
||||||
scrollableState,
|
scrollableState,
|
||||||
velocityScalar: isDesktopOrWeb ? 0.125 : 0.02,
|
velocityScalar: isDesktopOrWeb ? 0.15 : 0.02,
|
||||||
minimumAutoScrollDelta: isDesktopOrWeb ? 0.07 : 0.004,
|
minimumAutoScrollDelta: isDesktopOrWeb ? 0.07 : 0.004,
|
||||||
maxAutoScrollDelta: isDesktopOrWeb ? 2.75 : 0.053,
|
maxAutoScrollDelta: isDesktopOrWeb ? 3.5 : 0.053,
|
||||||
|
animationDuration: Duration.zero,
|
||||||
onScrollViewScrolled: () {
|
onScrollViewScrolled: () {
|
||||||
_notifyScrollViewScrolledListeners();
|
_notifyScrollViewScrolledListeners();
|
||||||
if (!isDesktopOrWeb) {
|
if (!isDesktopOrWeb) {
|
||||||
|
|
|
||||||
|
|
@ -150,10 +150,13 @@ class EdgeDraggingAutoScroller {
|
||||||
required this.velocityScalar,
|
required this.velocityScalar,
|
||||||
double minimumAutoScrollDelta = 1.0,
|
double minimumAutoScrollDelta = 1.0,
|
||||||
double maxAutoScrollDelta = 20.0,
|
double maxAutoScrollDelta = 20.0,
|
||||||
|
Duration? animationDuration,
|
||||||
}) : assert(minimumAutoScrollDelta >= 0),
|
}) : assert(minimumAutoScrollDelta >= 0),
|
||||||
assert(maxAutoScrollDelta >= minimumAutoScrollDelta),
|
assert(maxAutoScrollDelta >= minimumAutoScrollDelta),
|
||||||
_minimumAutoScrollDelta = minimumAutoScrollDelta,
|
_minimumAutoScrollDelta = minimumAutoScrollDelta,
|
||||||
_maxAutoScrollDelta = maxAutoScrollDelta;
|
_maxAutoScrollDelta = maxAutoScrollDelta,
|
||||||
|
_animationDuration =
|
||||||
|
animationDuration ?? const Duration(milliseconds: 5);
|
||||||
|
|
||||||
/// The [Scrollable] this auto scroller is scrolling.
|
/// The [Scrollable] this auto scroller is scrolling.
|
||||||
final ScrollableState scrollable;
|
final ScrollableState scrollable;
|
||||||
|
|
@ -180,6 +183,8 @@ class EdgeDraggingAutoScroller {
|
||||||
/// moving rather than treat it as too small to scroll.
|
/// moving rather than treat it as too small to scroll.
|
||||||
final double _minimumAutoScrollDelta;
|
final double _minimumAutoScrollDelta;
|
||||||
final double _maxAutoScrollDelta;
|
final double _maxAutoScrollDelta;
|
||||||
|
final Duration _animationDuration;
|
||||||
|
Duration? _currentDuration;
|
||||||
double? _previousScrollDelta;
|
double? _previousScrollDelta;
|
||||||
|
|
||||||
late Rect _dragTargetRelatedToScrollOrigin;
|
late Rect _dragTargetRelatedToScrollOrigin;
|
||||||
|
|
@ -212,10 +217,11 @@ class EdgeDraggingAutoScroller {
|
||||||
///
|
///
|
||||||
/// If the scrollable is already scrolling, calling this method updates the
|
/// If the scrollable is already scrolling, calling this method updates the
|
||||||
/// previous dragTarget to the new value and continues scrolling if necessary.
|
/// previous dragTarget to the new value and continues scrolling if necessary.
|
||||||
void startAutoScrollIfNecessary(Rect dragTarget) {
|
void startAutoScrollIfNecessary(Rect dragTarget, {Duration? duration}) {
|
||||||
final Offset deltaToOrigin = scrollable.deltaToScrollOrigin;
|
final Offset deltaToOrigin = scrollable.deltaToScrollOrigin;
|
||||||
_dragTargetRelatedToScrollOrigin =
|
_dragTargetRelatedToScrollOrigin =
|
||||||
dragTarget.translate(deltaToOrigin.dx, deltaToOrigin.dy);
|
dragTarget.translate(deltaToOrigin.dx, deltaToOrigin.dy);
|
||||||
|
_currentDuration = duration;
|
||||||
if (_scrolling) {
|
if (_scrolling) {
|
||||||
// The change will be picked up in the next scroll.
|
// The change will be picked up in the next scroll.
|
||||||
return;
|
return;
|
||||||
|
|
@ -228,9 +234,10 @@ class EdgeDraggingAutoScroller {
|
||||||
void stopAutoScroll() {
|
void stopAutoScroll() {
|
||||||
_scrolling = false;
|
_scrolling = false;
|
||||||
_previousScrollDelta = null;
|
_previousScrollDelta = null;
|
||||||
|
_currentDuration = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _scroll({Duration? duration}) async {
|
Future<void> _scroll() async {
|
||||||
try {
|
try {
|
||||||
final RenderBox scrollRenderBox =
|
final RenderBox scrollRenderBox =
|
||||||
scrollable.context.findRenderObject()! as RenderBox;
|
scrollable.context.findRenderObject()! as RenderBox;
|
||||||
|
|
@ -354,13 +361,13 @@ class EdgeDraggingAutoScroller {
|
||||||
}
|
}
|
||||||
await scrollable.position.moveTo(
|
await scrollable.position.moveTo(
|
||||||
newOffset,
|
newOffset,
|
||||||
duration: duration,
|
duration: _currentDuration ?? _animationDuration,
|
||||||
curve: Curves.linear,
|
curve: Curves.linear,
|
||||||
clamp: true,
|
// clamp: true,
|
||||||
);
|
);
|
||||||
onScrollViewScrolled?.call();
|
onScrollViewScrolled?.call();
|
||||||
if (_scrolling) {
|
if (_scrolling) {
|
||||||
await _scroll(duration: duration);
|
await _scroll();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint(e.toString());
|
debugPrint(e.toString());
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue