Skip to content

Conversation

@LongCatIsLooong
Copy link
Contributor

@LongCatIsLooong LongCatIsLooong commented Jun 29, 2020

Description

This PR makes flinging velocity platform-dependent. We can't reliably correct the flinging velocity on iOS in the friction simulation because the velocity estimation is done differently on iOS. This change brings the initial scroll velocity very close to what scrollViewWillEndDragging(_:withVelocity:targetContentOffset:) reports in the scroll_overlay app, also since the final scroll distance (the delta) of a free scroll solely depends on the initial velocity, this in theory should also make the amount the scrollable scrolls during free scrolling match iOS (it's still not as close as it could be because of pixel snapping on iOS and another minor difference in friction simulation, but from the results below it seems this should be good enough).

Test results (using a modified version of the scroll_overlay app):

test run 1

trigger velocity: 4030.787700, target offset: 2135.000000, scrollOffset delta: 2008.500000
2020-06-29 00:50:58.828681-0700 Runner[5062:3670119] flutter: goBallistic with initial velocity: 4030.6899249427292
2020-06-29 00:50:58.828743-0700 Runner[5062:3670119] flutter: start pixel: 258.6666666666667
2020-06-29 00:51:01.815903-0700 Runner[5062:3669876] velocityY: 0.000000
2020-06-29 00:51:01.849800-0700 Runner[5062:3670119] flutter: becomes Idle. Pixels: 2266.561898725746

In this run scrollViewWillEndDragging(_:withVelocity:targetContentOffset:) reported an initial velocity of 4030.787700 and a scroll distance of 2008.500000, while flutter reported 4030.6899249427292 and 2266.561898725746-258.6666666666667= 2007.89523206 respectively.

test run 2

2020-06-29 01:02:29.504894-0700 Runner[5116:3673262] trigger velocity: 6895.866228, target offset: 3816.500000, scrollOffset delta: 3439.500000
2020-06-29 01:02:29.531646-0700 Runner[5116:3673481] flutter: goBallistic with initial velocity: 6895.867438846153
2020-06-29 01:02:29.531713-0700 Runner[5116:3673481] flutter: start pixel: 455.0
2020-06-29 01:02:32.778637-0700 Runner[5116:3673262] velocityY: 0.000000
2020-06-29 01:02:32.812310-0700 Runner[5116:3673481] flutter: becomes Idle. Pixels: 3893.693637211801

this time it's 6895.866228 vs 6895.867438846153 and 3439.500000 vs 3438.69363721.

Related Issues

Fixes #11772

Related PR

adopted some changes from #59623 for better results.

Tests

I added the following tests:

FreeScrollStartVelocityTracker.getVelocity throws when no points, etc.

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Did any tests fail when you ran them? Please read Handling breaking changes.

  • No, no existing tests failed, so this is not a breaking change.

@fluttergithubbot fluttergithubbot added framework flutter/packages/flutter repository. See also f: labels. work in progress; do not review labels Jun 29, 2020
@LongCatIsLooong LongCatIsLooong added the platform-ios iOS applications specifically label Jun 29, 2020
@LongCatIsLooong LongCatIsLooong requested a review from xster June 29, 2020 17:53
@LongCatIsLooong LongCatIsLooong marked this pull request as ready for review June 29, 2020 17:54
@LongCatIsLooong LongCatIsLooong added f: scrolling Viewports, list views, slivers, etc. and removed work in progress; do not review labels Jun 29, 2020
@passsy
Copy link
Contributor

passsy commented Jul 9, 2020

Good job! I tested it with the scroll_overlay PR#2 project including the changes in #59623.

scroll_test2

Copy link
Member

@xster xster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general approach (e.g. final Offset estimatedVelocity = _previousVelocityAt(-2) * 0.6 + _previousVelocityAt(-1) * 0.35 + _previousVelocityAt(0) * 0.05;) lgtm

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this will be the first place a user is exposed to the term "velocity tracker", describe what it is or reference another doc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe briefly describe what's special about iOS scroll velocity to help bootstrap the next maintainer

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still not too clear what the difference is and why this needs to be a separate class rather than changing VelocityTracker.

Copy link
Contributor Author

@LongCatIsLooong LongCatIsLooong Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean the difference in terms of the strategies used? Does

/// A [VelocityTracker] subclass that employs a weighted average strategy to
/// estimate the velocity of the associated pointer, to match iOS scroll view's
/// fling velocity calculation.

sound better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As opposed to what though. I was looking for a text that saves the next maintainer from seeing thing as redundant, try to merge the 2 classes into one, spend 2 hours and then realized that the approach for the 2 are conceptually different (which the maintainer could have discovered in 10s by reading this text)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a simple comparison of the 2 velocity tracker classes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this name? Either somehow describe the "free scroll start" nature of the velocity tracking in the class doc or just call this ios velocity tracker.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we wanted to avoid having iOS in the name? Would be nice to know that I was mistaken.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understood this comment

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also seems like you're always using exactly 3 samples no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"4 _PointAtTime samples" is what I meant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Horizontal/VerticalDragGestureRecognizer.isFlingGesture has a threshold for VelocityEstimate.offset for it to be a fling:
https://api.flutter.dev/flutter/gestures/VerticalDragGestureRecognizer/isFlingGesture.html

Initially I used 4 samples and that broke some tests so I had to record more points. Will point to VerticalDragGestureRecognizer.isFlingGesture in the comments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds stronger than what the code seems to be doing. You're just weighing the initial velocity more rather than matching the initial velocity no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to say this is the velocity of the scroll view not that of the gesture. Reworded.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"initial free scrolling speed" is a bit vague

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add to the velocity_tracker_bench microbenchmark too

@goderbauer
Copy link
Member

fly-by comment: The analyzer is complaining.

Copy link
Member

@xster xster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I was out last few weeks. Thanks for the clean up! LGTM

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still not too clear what the difference is and why this needs to be a separate class rather than changing VelocityTracker.

@goderbauer
Copy link
Member

(PR triage): looks like some nested scrollview tests are failing.

@LongCatIsLooong LongCatIsLooong force-pushed the ios-scroll-velocity branch 3 times, most recently from 8db3b82 to 0dcec67 Compare July 30, 2020 01:17
@LongCatIsLooong
Copy link
Contributor Author

Had to use microseconds instead of milliseconds in flingTo to ensure the velocity samples' timestamps are monotonically increasing. Tests should be passing now.

@LongCatIsLooong
Copy link
Contributor Author

@xster @goderbauer should be ready for review now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<optional at this point, up to your judgement> can this just be done by composition? i.e. most platforms use a VelocityTracker with a VelocitySampleScorer of [1, 1, 1, 1, ...] and iOS uses a VelocityTracker with a VelocitySampleScorere of [8, 5, 2, 1] or something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean the weighted average can be expressed in terms of a least-squares estimator? Not sure how I can achieve that, could you elaborate?

@xster
Copy link
Member

xster commented Aug 3, 2020

LGTM. Up to you at this point if you want to use composition or just have 2 classes.

@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • Please get at least one approved review before re-applying this label. Reviewers: If you left a comment approving, please use the "approve" review action instead.
  • The status or check suite web_smoke_test has failed. Please fix the issues identified (or deflake) before re-applying this label.

@Piinks Piinks added the a: fidelity Matching the OEM platforms better label Aug 10, 2020
Copy link
Member

@goderbauer goderbauer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

this.dragStartBehavior = DragStartBehavior.start,
this.velocityTrackerBuilder = _defaultBuilder,
}) : assert(dragStartBehavior != null),
//this.velocityTrackerBuilder = velocityTrackerBuilder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this?

@fluttergithubbot fluttergithubbot merged commit cea055e into flutter:master Aug 12, 2020
@LongCatIsLooong LongCatIsLooong deleted the ios-scroll-velocity branch August 12, 2020 20:36
mingwandroid pushed a commit to mingwandroid/flutter that referenced this pull request Sep 6, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

a: fidelity Matching the OEM platforms better f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. platform-ios iOS applications specifically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fine-tune fling velocity

7 participants