New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ClampingScrollSimulation decays sooner and goes less far than native Android scrolling #119875
Comments
I've done some investigation of this issue already, and have a diagnosis. Android uses (in With the spline curve, to find the scroll position In Here's a set of graphs comparing the Android scroll physics and what's in So what's needed is to use a curve that better approximates the Android curve. In particular, at There's a bonus issue with the
Instead the velocity actually increases over the last 200ms or so, before abruptly stopping when the simulation ends. In the Android scroll physics, the velocity decreases continuously to reach zero at the end. I originally noticed this bonus issue thanks to these graphs; when interacting as a user I'd never put my finger on it. But now that I know about it, it's very conspicuous to me when using To fix this bonus issue and get a smooth stop, we want the curve to have velocity 0 at |
Reproducible using the code sample and steps outlined above. Labeling based on the information provided above. recordingtelegram-cloud-document-4-5974508209786850387.mp4flutter doctor -v
|
Thanks @danagbemava-nc for that recording! Yes, that exactly. I plan to send a PR to fix this issue. Before that, I'll send a platform_tests PR or two to update the Before I send a PR, it would be helpful to get some feedback on the possible solutions. I see several options:
Here's a set of graphs showing Android's curve; the current cubic from You can see that the degree-10 polynomial (in red) hugs the Android spline (in blue) much more closely than either cubic, but still imperfectly. |
Aha, and just now I've done the code archaeology that I probably should have done sooner, and found the previous work on this issue:
Cc'ing @grouma and @Piinks as the authors of those previous PRs. (I did try searching the tracker, and missed those; the closest I found was #103762 which is about iOS. But I see that both the above PRs went for option 3 from my previous comment: using linear interpolation from a table, in order to go for perfect fidelity. That's the option I was thinking was probably best. I guess those PRs confirm that others agree. I'll spend some time studying those previous PRs (especially the later version) and the issues that caused the reverts. |
@gnprice thank you very much for your detailed analysis! This has been a challenging issue to resolve. I look forward to hearing what your thoughts are after some research. |
OK, I've now done this. I'm going to file a few more issues reflecting what I've found, then a PR or two with a possible way forward. |
Fixes flutter#120338. Fixes flutter#119875. Fixes flutter#113424. Fixes most of flutter#16371, as the combined symptom of those three. (There's still flutter#120345, and possibly other contributing factors, remaining.) This replaces the implementation of ClampingScrollSimulation with a new version that better matches the Android scroll physics it's intended to match. The new implementation is a version of the Android curve which has been adjusted so that it behaves in a physically reasonable way, in order to satisfy an invariant which the Flutter scroll protocol relies on. Because the old ClampingScrollSimulation didn't satisfy that invariant either, it suffered from a bug (flutter#120338) where restarting the simulation with new metrics would have the side effect of adding friction, making a fling go about 15% less far. So this fixes flutter#120338. The new implementation also goes the same total distance as the Android scroll physics, whereas the existing version would go about 7% less far (stacking with the 15% reduction when the other issue was triggered.) That fixes flutter#119875. Finally, the new implementation comes to a smooth stop, like Android does, whereas the existing version would speed slightly up before abruptly stopping. That fixes flutter#113424. The new implementation's curve is the unique curve that both goes the same total distance as Android's for every possible starting velocity, and meets the Flutter scroll protocol's ballistic invariant. So in that sense this is the canonical way of fixing up the Android behavior to something physically reasonable, or something that works correctly in Flutter.
Incredible write up! Thank you. Before I landed #77497, I did attempt another approach. I simply updated the cubic approximation to match the boundary conditions and thus have the velocity eventually decelerate to zero. As you noted above, this updated approximation is not truly accurate which I noticed. I then decided to copy the logic which has issues as you also noted. |
Thanks!
Makes sense. That would have been the same cubic shown in green in my graphs above (#119875 (comment)). It would have fixed this issue and #113424, but #120338 would have still been present, with I think a slightly smaller effect because the initial deceleration would be slightly less. |
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of |
On Android, when the user attempts to scroll quickly using a "fling" gesture, the scroll doesn't go as far or as fast as it would have in a native Android scrolling view. In a long list this can make scrolling feel sluggish, or not easy, or not responsive.
One reason for this behavior is that Flutter's
ClampingScrollSimulation
, which is meant to match Android's scroll physics (and is used by default on Android and other non-Apple platforms), in fact uses a curve that decays faster than the Android curve, and goes less far in total. When the simulation is complete, the distance traveled is about 7.2% less than the Android scroll physics would travel.(This isn't the only factor contributing to the overall slowness of the scroll; I'll file other issues separately.)
Related issue:
Steps to Reproduce
platform_tests/scroll_overlay
app on an Android device.Expected results:
The Flutter list should scroll the same distance as the Android list, so that corresponding list items are aligned with each other.
Actual results:
The Flutter list goes substantially less far than the Android list.
Specifically, when I try this on the current version of
scroll_overlay
(at flutter/platform_tests@1d797b8 ), I see "Android 94" next to "Flutter 81".That version has item heights that vary through the list and don't quite agree between Android and Flutter, making the numbers a bit hard to interpret. In a revised
scroll_overlay
with fixed heights (which I'll send a platform_tests PR for), I see "Android 202" next to "Flutter 189".Logs
The text was updated successfully, but these errors were encountered: