Skip to content

Conversation

@passsy
Copy link
Contributor

@passsy passsy commented Jun 17, 2020

Description

On iOS, lists with differently sized items have bigger damping than lists with equally sized items.

During a fling the maxScrollExtent continuously changes (slightly) when the items aren't equally sized. This causes a new simulation to be created. The FastBouncingScrollPhysics used for iOS, decreases the velocity by 9% every time it is created.
This problem wasn't tested in the existing scroll_overlay platform test. All items there have the same size causing the simulation to only be created once.

This PR removes the velocity change when creating the simulation and tweaks the friction of the FrictionSimulation to match the native iOS behavior closely for both scenarios.

The new damping isn't pixel-perfect (if that's even possible) but close. The focus of this PR is that lists with equally and unequally sized cells now behave the same on iOS.

Before (damped) After
damped after

Related Issues

Related #11772
Fixes #32448

Tests

For testing, I updated the scroll_overlay PR#2 test project to use different sized cells.

I tested with iPhone XR, iPhone SE and Pixel 4

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

  • No, this PR doesn't change the public or internal API.

@fluttergithubbot fluttergithubbot added the framework flutter/packages/flutter repository. See also f: labels. label Jun 17, 2020
@fluttergithubbot
Copy link
Contributor

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@passsy passsy force-pushed the feature/reduce_ios_damping branch from f7e4e6f to 74924c1 Compare June 17, 2020 01:51
Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a comment

Choose a reason for hiding this comment

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

Thank you for fixing this! And sorry for the delay, it took me longer than expected to do the research. I think we might want to keep using the 0.135 drag coefficient, but the other changes look good!

FYI the definition of breaking changes has been updated just recently, changing tests located in the test folder alone is no longer considered breaking.

I have yet to find out what caused the difference in flinging velocity, will post my updates in #11772.

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for updating this!

Copy link
Contributor

@LongCatIsLooong LongCatIsLooong Jun 25, 2020

Choose a reason for hiding this comment

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

The 0.135 coefficient is actually accurate. You can verify this in a native UIScrollView (or UITableView) by adding the following code to its delegate and flinging the scroll view:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
  let actualTargetVerticalOffset = targetContentOffset.pointee.y
  let computedVerticalOffset = scrollView.contentOffset.y - (velocity.y - 0.01)/(log(scrollView.decelerationRate.rawValue))
  print("actual target vertical offset: \(actualTargetVerticalOffset), computed from velocity: \(computedVerticalOffset)")
}

The computed value is going to be very close to the actual content offset (but not exactly the same, I guess there's rounding/flooring happening in the actual implementation, so the final value snaps to physical pixels).

The default scrollView.decelerationRate value is 0.998 (.normal), but the velocity is in a different unit here in scrollViewWillEndDragging (pixel per millisecond I guess), thus the 0.135 (0.998^1000).

Copy link
Contributor

Choose a reason for hiding this comment

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

The velocity we use to create the ballistic activity is responsible for the most content offset error here.

@Piinks Piinks added a: fidelity Matching the OEM platforms better platform-ios iOS applications specifically f: scrolling Viewports, list views, slivers, etc. labels Jul 6, 2020
@goderbauer
Copy link
Member

(PR triage) @LongCatIsLooong @passsy What is the status of this PR? Should it be closed in favor of #60501?

passsy added 2 commits July 9, 2020 01:51
…items

As pointed out in flutter#32448, the velocity shouldn't be decreased when creating the simulation. The current solution only works for lists where all items have the same size. Lists with different sized items recreate the simulation over and over again (because the maxScrollExtent slightly changes), reducing the velocity with each call by 9%. The velocity should not depend on how often the simulation gets created!
Instead I tweaked the damping value of the FrictionSimulation to match the native behavior more closely.

For testing, I updated the [scroll_overlay](flutter/platform_tests#2) test project to use different sized cells.

The new damping isn't pixel-perfect. I'm not even sure it is possible at all. But at least lists with equally and unequally sized cells now behave the same.

Related flutter#11772
@passsy passsy force-pushed the feature/reduce_ios_damping branch from 0047a8f to 72bb989 Compare July 8, 2020 23:57
@passsy
Copy link
Contributor Author

passsy commented Jul 9, 2020

@LongCatIsLooong I reverted the drag from FrictionSimulation back to 0.135. This only resolves the excessive damping when list items have different sizes. It now scrolls - faster - like lists with equally sized items.

Before (damped) WIP drag=0.07 After drag=0.135
damped after after2

@LongCatIsLooong
Copy link
Contributor

@goderbauer @passsy I didn't add tests in #60501 to cover the case where the viewport needs to apply a new content dimension. I was hoping that we can wait for both PRs to be reviewed and then merge them together.

Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a comment

Choose a reason for hiding this comment

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

LGTM. Thank you for fixing this long-standing issue (and updating the scroll_overlay app)! I'll try to merge this PR and #60501 together to prevent potential regression.
You may need to merge the latest upstream/master to the PR branch to fix the "docs-linux" CI failure.

@fluttergithubbot fluttergithubbot merged commit 12b8d9d into flutter:master Aug 8, 2020
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 8, 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.

Scroll physics on iOS is excessively damped

7 participants