@@ -686,6 +686,17 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
686
686
return scrollableExtent * thumbOffsetLocal / thumbMovableExtent;
687
687
}
688
688
689
+ /// The thumb's corresponding scroll offset in the track.
690
+ double getThumbScrollOffset () {
691
+ final double scrollableExtent = _lastMetrics! .maxScrollExtent - _lastMetrics! .minScrollExtent;
692
+
693
+ final double fractionPast = (scrollableExtent > 0 )
694
+ ? clampDouble (_lastMetrics! .pixels / scrollableExtent, 0.0 , 1.0 )
695
+ : 0 ;
696
+
697
+ return fractionPast * (_traversableTrackExtent - _thumbExtent);
698
+ }
699
+
689
700
// Converts between a scroll position and the corresponding position in the
690
701
// thumb track.
691
702
double _getScrollToTrack (ScrollMetrics metrics, double thumbExtent) {
@@ -1446,15 +1457,15 @@ class RawScrollbar extends StatefulWidget {
1446
1457
/// Provides defaults gestures for dragging the scrollbar thumb and tapping on the
1447
1458
/// scrollbar track.
1448
1459
class RawScrollbarState <T extends RawScrollbar > extends State <T > with TickerProviderStateMixin <T > {
1449
- Offset ? _dragScrollbarAxisOffset;
1460
+ Offset ? _startDragScrollbarAxisOffset;
1461
+ double ? _startDragThumbOffset;
1450
1462
ScrollController ? _currentController;
1451
1463
Timer ? _fadeoutTimer;
1452
1464
late AnimationController _fadeoutAnimationController;
1453
1465
late Animation <double > _fadeoutOpacityAnimation;
1454
1466
final GlobalKey _scrollbarPainterKey = GlobalKey ();
1455
1467
bool _hoverIsActive = false ;
1456
1468
1457
-
1458
1469
/// Used to paint the scrollbar.
1459
1470
///
1460
1471
/// Can be customized by subclasses to change scrollbar behavior by overriding
@@ -1688,30 +1699,30 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
1688
1699
1689
1700
void _updateScrollPosition (Offset updatedOffset) {
1690
1701
assert (_currentController != null );
1691
- assert (_dragScrollbarAxisOffset != null );
1702
+ assert (_startDragScrollbarAxisOffset != null );
1703
+ assert (_startDragThumbOffset != null );
1692
1704
1693
1705
final ScrollPosition position = _currentController! .position;
1694
1706
late double primaryDelta;
1695
1707
switch (position.axisDirection) {
1696
1708
case AxisDirection .up:
1697
- primaryDelta = _dragScrollbarAxisOffset ! .dy - updatedOffset.dy;
1709
+ primaryDelta = _startDragScrollbarAxisOffset ! .dy - updatedOffset.dy;
1698
1710
break ;
1699
1711
case AxisDirection .right:
1700
- primaryDelta = updatedOffset.dx - _dragScrollbarAxisOffset ! .dx;
1712
+ primaryDelta = updatedOffset.dx - _startDragScrollbarAxisOffset ! .dx;
1701
1713
break ;
1702
1714
case AxisDirection .down:
1703
- primaryDelta = updatedOffset.dy - _dragScrollbarAxisOffset ! .dy;
1715
+ primaryDelta = updatedOffset.dy - _startDragScrollbarAxisOffset ! .dy;
1704
1716
break ;
1705
1717
case AxisDirection .left:
1706
- primaryDelta = _dragScrollbarAxisOffset ! .dx - updatedOffset.dx;
1718
+ primaryDelta = _startDragScrollbarAxisOffset ! .dx - updatedOffset.dx;
1707
1719
break ;
1708
1720
}
1709
1721
1710
1722
// Convert primaryDelta, the amount that the scrollbar moved since the last
1711
- // time _updateScrollPosition was called , into the coordinate space of the scroll
1723
+ // time when drag started , into the coordinate space of the scroll
1712
1724
// position, and jump to that position.
1713
- final double scrollOffsetLocal = scrollbarPainter.getTrackToScroll (primaryDelta);
1714
- final double scrollOffsetGlobal = scrollOffsetLocal + position.pixels;
1725
+ final double scrollOffsetGlobal = scrollbarPainter.getTrackToScroll (primaryDelta + _startDragThumbOffset! );
1715
1726
if (scrollOffsetGlobal != position.pixels) {
1716
1727
// Ensure we don't drag into overscroll if the physics do not allow it.
1717
1728
final double physicsAdjustment = position.physics.applyBoundaryConditions (position, scrollOffsetGlobal);
@@ -1784,7 +1795,8 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
1784
1795
}
1785
1796
_fadeoutTimer? .cancel ();
1786
1797
_fadeoutAnimationController.forward ();
1787
- _dragScrollbarAxisOffset = localPosition;
1798
+ _startDragScrollbarAxisOffset = localPosition;
1799
+ _startDragThumbOffset = scrollbarPainter.getThumbScrollOffset ();
1788
1800
}
1789
1801
1790
1802
/// Handler called when a currently active long press gesture moves.
@@ -1803,7 +1815,6 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
1803
1815
return ;
1804
1816
}
1805
1817
_updateScrollPosition (localPosition);
1806
- _dragScrollbarAxisOffset = localPosition;
1807
1818
}
1808
1819
1809
1820
/// Handler called when a long press has ended.
@@ -1816,7 +1827,8 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
1816
1827
return ;
1817
1828
}
1818
1829
_maybeStartFadeoutTimer ();
1819
- _dragScrollbarAxisOffset = null ;
1830
+ _startDragScrollbarAxisOffset = null ;
1831
+ _startDragThumbOffset = null ;
1820
1832
_currentController = null ;
1821
1833
}
1822
1834
@@ -1958,7 +1970,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
1958
1970
scrollbarPainter.update (metrics, metrics.axisDirection);
1959
1971
}
1960
1972
} else if (notification is ScrollEndNotification ) {
1961
- if (_dragScrollbarAxisOffset == null ) {
1973
+ if (_startDragScrollbarAxisOffset == null ) {
1962
1974
_maybeStartFadeoutTimer ();
1963
1975
}
1964
1976
}
0 commit comments