Skip to content

Commit 79324c9

Browse files
gnpricechrisbobbe
authored andcommitted
scroll: Apply a min velocity in ScrollToEndSimulation
This makes it possible to see in a self-contained way, in this class's own code, that it always starts moving at a velocity that isn't zero, or less than zero, or at risk of being conflated with zero. This doesn't have a big effect in practice, because the only call site already does something else whenever the distance to travel is negative or very close to zero. But there is a small range -- namely where the distance to travel is between 1 and 12 physical pixels, given the default behavior of ScrollPhysics.toleranceFor -- in which this minimum speed does apply.
1 parent 9074b77 commit 79324c9

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

lib/widgets/scrolling.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,18 @@ class InertialSimulation extends Simulation { // TODO(upstream)
8686
/// Instead this takes a smoothed-out approximation of such a trajectory.
8787
class ScrollToEndSimulation extends InertialSimulation {
8888
factory ScrollToEndSimulation(ScrollPosition position) {
89+
final tolerance = position.physics.toleranceFor(position);
8990
final startPosition = position.pixels;
9091
final estimatedEndPosition = position.maxScrollExtent;
9192
final velocityForMinDuration = (estimatedEndPosition - startPosition)
9293
/ (minDuration.inMilliseconds / 1000.0);
93-
assert(velocityForMinDuration > 0);
94-
final velocity = clampDouble(velocityForMinDuration, 0, topSpeed);
94+
final velocity = clampDouble(velocityForMinDuration,
95+
// If the starting position is beyond the estimated end
96+
// (i.e. `velocityForMinDuration < 0`), or very close to it,
97+
// then move forward at a small positive velocity.
98+
// Let the overscroll handling bring the position to exactly the end.
99+
2 * tolerance.velocity,
100+
topSpeed);
95101
return ScrollToEndSimulation._(startPosition, velocity);
96102
}
97103

test/widgets/scrolling_test.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,27 @@ void main() {
297297
debugDefaultTargetPlatformOverride = null;
298298
});
299299

300+
testWidgets('starting very near end, apply min speed', (tester) async {
301+
await prepare(tester, topHeight: 400, bottomHeight: 400);
302+
// Verify the assumption used for constructing the example numbers below.
303+
check(position.physics.toleranceFor(position).velocity)
304+
.isCloseTo(20/3, .01);
305+
306+
position.jumpTo(398);
307+
await tester.pump();
308+
check(position.extentAfter).equals(2);
309+
310+
position.scrollToEnd();
311+
await tester.pump();
312+
check(position.extentAfter).equals(2);
313+
314+
// Reach the end in just 150ms, not 300ms.
315+
await tester.pump(Duration(milliseconds: 75));
316+
check(position.extentAfter).equals(1);
317+
await tester.pump(Duration(milliseconds: 75));
318+
check(position.extentAfter).equals(0);
319+
});
320+
300321
testWidgets('on overscroll, stop', (tester) async {
301322
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
302323
await prepare(tester, topHeight: 400, bottomHeight: 1000);

0 commit comments

Comments
 (0)