Unverified Commit ee921e63 authored by Trym Nilsen's avatar Trym Nilsen Committed by GitHub

Apply carriedVelocity unless substantially different (#79382)

parent d0513364
......@@ -274,6 +274,14 @@ class ScrollDragController implements Drag {
static const Duration momentumRetainStationaryDurationThreshold =
Duration(milliseconds: 20);
/// The minimum amount of velocity needed to apply the [carriedVelocity] at
/// the end of a drag. Expressed as a factor. For example with a
/// [carriedVelocity] of 2000, we will need a velocity of at least 1000 to
/// apply the [carriedVelocity] as well. If the velocity does not meet the
/// threshold the the [carriedVelocity] is lost. Decided by fair eyeballing
/// with the scroll_overlay platform test.
static const double momentumRetainVelocityThresholdFactor = 0.5;
/// Maximum amount of time interval the drag can have consecutive stationary
/// pointer update events before needing to break the
/// [motionStartDistanceThreshold] to start motion again.
......@@ -390,9 +398,17 @@ class ScrollDragController implements Drag {
velocity = -velocity;
_lastDetails = details;
if (_retainMomentum) {
// Build momentum only if dragging in the same direction.
if (_retainMomentum && velocity.sign == carriedVelocity!.sign)
final bool isFlingingInSameDirection = velocity.sign == carriedVelocity!.sign;
// Build momentum only if the velocity of the last drag was not
// substantially lower than the carried momentum.
final bool isVelocityNotSubstantiallyLessThanCarriedMomentum =
velocity.abs() > carriedVelocity!.abs() * momentumRetainVelocityThresholdFactor;
if(isFlingingInSameDirection && isVelocityNotSubstantiallyLessThanCarriedMomentum) {
velocity += carriedVelocity!;
}
}
delegate.goBallistic(velocity);
}
......
......@@ -178,6 +178,23 @@ void main() {
expect(getScrollVelocity(tester), moreOrLessEquals(1000.0));
});
testWidgets('A slower final fling does not apply carried momentum', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
await tester.pump(); // trigger fling
await tester.pump(const Duration(milliseconds: 10));
// Repeat the exact same motion to build momentum.
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
await tester.pump(); // trigger the second fling
await tester.pump(const Duration(milliseconds: 10));
// Make a final fling that is much slower.
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 200.0);
await tester.pump(); // trigger the third fling
await tester.pump(const Duration(milliseconds: 10));
// expect that there is no carried velocity
expect(getScrollVelocity(tester), lessThan(200.0));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('No iOS/macOS momentum build with flings in opposite directions', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment