-
Notifications
You must be signed in to change notification settings - Fork 28.6k
NestedScrollView
's outer scrollable jumping with BouncingScrollPhysics
due to double
precision errors
#138319
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
Conversation
@Michal-MK thanks for the contribution. Looks like this PR is failing some checks. Can you please take a look and fix those up? Thanks! |
@goderbauer I can decode the Linux Analyze check, which is clear to me, I have a TODO in tests, but the issue is I do not know how to write tests for this fix. For the other 6 failing checks I have no idea what the output is trying to tell me. I looked at the "undestading a LUCI build failure", but that to me appears to describe something else.
|
Apart from tree-status all tests should pass, I'll wait and see if a test for this will be needed/asked for. |
e2cf20b
to
b416c9d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution @Michal-MK!
This will need a test to verify it works as expected, and to prevent us from accidentally undoing this in the future. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @Michal-MK welcome. Thanks for contributing!
await tester.pumpWidget(build()); | ||
|
||
outerController.addListener(() { | ||
assert(false); // We do not want this to be called. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? The outer should scroll before the inner, why would the outer not scroll?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I understand the test is that we have:
tester.drag(find.byKey(innerKey), const Offset(0, 2000));
Which means dragging the finger down the screen (I believe). So we are immediately overscrolling and triggering the dampening effect of the spring. The total height is 300 + 64 + 800 from the individual components. 1164 < 2000. So we have technically 836 units to work with.
tester.fling(find.byKey(innerKey), const Offset(0, -600), 2000);
After that we immediately fling the finger up the screen. My understanding is that the total distance will be 600 units up and the 2000 just affects how quickly the 600 will happen.
Which equals 836 - 600 = 236. So we still have 236 units to spare before the outer scrollable should start scrolling. What does not fly is the spring does not actually "stretch" to 836 visually, but I have no idea how that is implemented. If this description makes sense I will add it to the test itself, but there is a possibility it is nonsense and I just do not understand what I wrote ;).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, it may be easier to understand if you add checks on what the actual position is before and after each gesture. What is the value of position.pixels for the outer and inner each time? For the nested scroll view in general, the inner should not scroll before the outer has fully scrolled to its end.
If we are dragging down first, overscrolling the outer, then flinging up, I would expect the outer to consume some of the distance flinging up before the inner receives any.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"For the nested scroll view in general, the inner should not scroll before the outer has fully scrolled to its end." - True, but since in the default state, the outer is at zero we are immediately overscrolling inner scrollable.
"If we are dragging down first, overscrolling the outer, then flinging up, I would expect the outer to consume some of the distance flinging up before the inner receives any." - the outer is not being overscrolled: This is the default state:
And this is the state after pulling down:
The outer scrollable does not move, and I checked that by adding a listener to the outer scroll view and pulled downwards, and indeed, I got no prints. I.e. the callback was never invoked.
outerController.addListener(() {
print('outerController: ${outerController.offset}, ${outerController.position}');
});
Since we are not supposed to assign a scroll controller to the inner scrollview I do not have output from that. But I did try a fling up, after overscrolling the inner scrollable, and it can actually be fairly strong and yet it does not trigger anything in the outer scrollable.
20231130_185335-small.mp4
The actual positions are in here:
#138319 (comment)
As can be seen, before it fluctuated between "immeasurable delta from 0" and 0 now it stays on 0. I do not know how to test that other than though the scroll controller not firing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the outer is not being overscrolled
Ah right I see. The inner is using bouncing scroll physics. Yup. So the inner overscrolls at the top, but then when the test flings the inner up, I expect the outer to consume some of the distance before the inner does.
Since we are not supposed to assign a scroll controller to the inner scrollview I do not have output from that.
The inner scroll controller is accessible through the inner key you have created in the test.
Can you add checks that validate the inner and outer positions at each step to the test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll try.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I added more asserts to the test, I did not find a way to obtain the controller from the previous setup so I just borrowed someone else's solution :). The outer scrollable does not move, it may be surprising but it's true (according to the expect()
and the .addListener()
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Michal-MK thanks for the update. It looks like there are a lot of failing tests currently, can you take a look?
await tester.pumpWidget(build()); | ||
|
||
outerController.addListener(() { | ||
assert(false); // We do not want this to be called. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, it may be easier to understand if you add checks on what the actual position is before and after each gesture. What is the value of position.pixels for the outer and inner each time? For the nested scroll view in general, the inner should not scroll before the outer has fully scrolled to its end.
If we are dragging down first, overscrolling the outer, then flinging up, I would expect the outer to consume some of the distance flinging up before the inner receives any.
Tests are failing randomly, as noted here: #138319 (comment). No idea how to decode the output. I just merged current master into it and it worked again. That was the case even before I added my test so i do not know what is causing it. |
So it seems that Linux web_canvaskit_tests_4 and Linux web_tests_0 are now failing consistently, but their output is still illegible: â��â��â��â��â��â��â��â��â� |
After spending more time with it I did find the tiny "show more details" button. There I finally got the actual output. Hmm why is GitHub's so broken then...? I modified the test to hopefully pass the two failing cases. |
|
||
await tester.drag(find.byKey(innerKey), const Offset(0, 2000)); // Over-scroll the inner Scrollable to the bottom | ||
|
||
const double endPosition = -1974.0862087158384; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than this complicated value, you could use the greaterThan
, moreOrLessEquals
, etc tools that flutter_test
provides.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since. we are essentially testing a double precision error, I included the exact value the controller had after the drag, but I can change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second thought I like how the math adds up, because later in the code I do: endValue + 600 which would then not work... If I used moreOrLessEquals
the delta would have to be really big. I could do moreOrLessEquals(-2000, delta: 100.0)
since 2000 is the drag
parameter, but I do not like how vague that becomes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok! We should probably add some context at least in a comment for future wonderers. Style guide has recommendations: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#avoid-mysterious-and-magical-numbers-that-lack-a-clear-derivation
expect(outer.offset, 0.0); | ||
expect(inner.offset, endPosition + 600); | ||
|
||
// Since there is a difference between scrolling on devices and the web absolute values are not checked... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I follow here. What was the failure this is working around?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before I had concrete values at each step, as seen in this commit, I then rewrote it since tests on Web were failing due to the controller reporting different values than seen on native platforms. I can remove the comment if that is intended.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change looks good, with added context in the test for that value. I will be OOO on vacation after today, so if you would not like to wait, another reviewer can be requested on the Discord. This change will need two approvals. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update @Michal-MK, and happy new year! This LGTM!
Happy new year to you and all of the Flutter team. Awesome framework, glad I could contribute. :) |
@Piinks Is there something on my part that needs doing? The "Google testing" test is now running for more than 5 days, is that intended? |
This still needs a second review, but I have rebased it to kick the Google testing shard. 👍 |
Hmm, I was not able to rebase since there is a merge conflict. Can you rebase with the master branch @Michal-MK? |
Struggling with the rebase, give me a minute :) |
…e outer scrollable to jump.
- added tests to check for flickering between 0/ less than 1e^(-10+) for outer scrollable (likely not intended as no tests were covering that)
Co-authored-by: Kate Lovett <[email protected]>
…ux web_tests_0 scroll differently than other platforms so constant values are not usable.
So, I finally won agains git rebase, unfortunately, the bot added some people for review, that was not intentional. @Piinks I do not see the Discord channel and I have not found any info on how to enable it on what is publicly available. |
Thanks for rebasing! Looks like that channel is restricted to contributors with commit access (members of flutter-hackers): https://github.com/flutter/flutter/wiki/Contributor-access Sorry for sharing something inaccessible. The channel is for seeking reviewers, so it should get picked up soon. 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
secondary LGTM
…crollPhysics` due to `double` precision errors (flutter/flutter#138319)
flutter/flutter@126302d...b840a60 2024-01-10 [email protected] Roll Flutter Engine from 3269fd84460d to b361a60ae224 (1 revision) (flutter/flutter#141271) 2024-01-10 [email protected] Roll Flutter Engine from a5d446da5495 to 3269fd84460d (1 revision) (flutter/flutter#141264) 2024-01-10 [email protected] Roll Flutter Engine from 3ccf66bed335 to a5d446da5495 (2 revisions) (flutter/flutter#141252) 2024-01-10 [email protected] Roll Flutter Engine from e57e418c02ae to 3ccf66bed335 (1 revision) (flutter/flutter#141241) 2024-01-10 [email protected] Roll Flutter Engine from 7e6f3d847e01 to e57e418c02ae (1 revision) (flutter/flutter#141240) 2024-01-10 [email protected] Roll Flutter Engine from 1cf2e0a603c7 to 7e6f3d847e01 (1 revision) (flutter/flutter#141237) 2024-01-10 [email protected] Roll Flutter Engine from 32bbf8be8d2c to 1cf2e0a603c7 (1 revision) (flutter/flutter#141232) 2024-01-10 [email protected] Roll Flutter Engine from 5b9d2132b7cd to 32bbf8be8d2c (1 revision) (flutter/flutter#141229) 2024-01-10 [email protected] Roll Flutter Engine from 941f268fc8bb to 5b9d2132b7cd (1 revision) (flutter/flutter#141228) 2024-01-10 [email protected] Roll Flutter Engine from 542fea9edae4 to 941f268fc8bb (3 revisions) (flutter/flutter#141224) 2024-01-10 [email protected] `NestedScrollView`'s outer scrollable jumping with `BouncingScrollPhysics` due to `double` precision errors (flutter/flutter#138319) 2024-01-10 [email protected] Roll Flutter Engine from 8c1501f3956d to 542fea9edae4 (1 revision) (flutter/flutter#141217) 2024-01-10 [email protected] Fix or except leaks. (flutter/flutter#141081) 2024-01-09 [email protected] Roll Flutter Engine from 693af0c699c5 to 8c1501f3956d (1 revision) (flutter/flutter#141215) 2024-01-09 [email protected] TextStyle: In copyWith, stop ignoring debugLabel when receiver has none (flutter/flutter#141141) 2024-01-09 [email protected] Roll Flutter Engine from a35e3b026e1d to 693af0c699c5 (5 revisions) (flutter/flutter#141209) 2024-01-09 [email protected] Replace deprecated `exists` in podhelper.rb (flutter/flutter#141169) 2024-01-09 [email protected] Correctly handle null case in ProcessText.queryTextActions (flutter/flutter#141205) 2024-01-09 [email protected] Add environment variable to leak tracking bots. (flutter/flutter#141137) 2024-01-09 [email protected] Reapply "Dynamic view sizing" (#140165) (flutter/flutter#140918) 2024-01-09 [email protected] Introduce new Form validation method (flutter/flutter#135578) 2024-01-09 [email protected] Update `RouteObserver` example and fix an error thrown (flutter/flutter#141166) 2024-01-09 [email protected] Upgrade leak_tracker. (flutter/flutter#141153) 2024-01-09 [email protected] [ci.yaml] Do not run packaging test on presubmit (flutter/flutter#141192) 2024-01-09 [email protected] Roll Flutter Engine from 036b39fa47fa to a35e3b026e1d (6 revisions) (flutter/flutter#141191) 2024-01-09 [email protected] Run tests on iOS 16 or iOS 17 (flutter/flutter#141178) 2024-01-09 [email protected] Remove conditions that depend on order. (flutter/flutter#141183) 2024-01-09 [email protected] Roll Flutter Engine from b3c8597df0e2 to 036b39fa47fa (1 revision) (flutter/flutter#141179) 2024-01-09 [email protected] resolved the issue of indeterminate CircularProgressIndicator.adaptive on Darwin (flutter/flutter#140947) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
flutter/flutter@126302d...b840a60 2024-01-10 [email protected] Roll Flutter Engine from 3269fd84460d to b361a60ae224 (1 revision) (flutter/flutter#141271) 2024-01-10 [email protected] Roll Flutter Engine from a5d446da5495 to 3269fd84460d (1 revision) (flutter/flutter#141264) 2024-01-10 [email protected] Roll Flutter Engine from 3ccf66bed335 to a5d446da5495 (2 revisions) (flutter/flutter#141252) 2024-01-10 [email protected] Roll Flutter Engine from e57e418c02ae to 3ccf66bed335 (1 revision) (flutter/flutter#141241) 2024-01-10 [email protected] Roll Flutter Engine from 7e6f3d847e01 to e57e418c02ae (1 revision) (flutter/flutter#141240) 2024-01-10 [email protected] Roll Flutter Engine from 1cf2e0a603c7 to 7e6f3d847e01 (1 revision) (flutter/flutter#141237) 2024-01-10 [email protected] Roll Flutter Engine from 32bbf8be8d2c to 1cf2e0a603c7 (1 revision) (flutter/flutter#141232) 2024-01-10 [email protected] Roll Flutter Engine from 5b9d2132b7cd to 32bbf8be8d2c (1 revision) (flutter/flutter#141229) 2024-01-10 [email protected] Roll Flutter Engine from 941f268fc8bb to 5b9d2132b7cd (1 revision) (flutter/flutter#141228) 2024-01-10 [email protected] Roll Flutter Engine from 542fea9edae4 to 941f268fc8bb (3 revisions) (flutter/flutter#141224) 2024-01-10 [email protected] `NestedScrollView`'s outer scrollable jumping with `BouncingScrollPhysics` due to `double` precision errors (flutter/flutter#138319) 2024-01-10 [email protected] Roll Flutter Engine from 8c1501f3956d to 542fea9edae4 (1 revision) (flutter/flutter#141217) 2024-01-10 [email protected] Fix or except leaks. (flutter/flutter#141081) 2024-01-09 [email protected] Roll Flutter Engine from 693af0c699c5 to 8c1501f3956d (1 revision) (flutter/flutter#141215) 2024-01-09 [email protected] TextStyle: In copyWith, stop ignoring debugLabel when receiver has none (flutter/flutter#141141) 2024-01-09 [email protected] Roll Flutter Engine from a35e3b026e1d to 693af0c699c5 (5 revisions) (flutter/flutter#141209) 2024-01-09 [email protected] Replace deprecated `exists` in podhelper.rb (flutter/flutter#141169) 2024-01-09 [email protected] Correctly handle null case in ProcessText.queryTextActions (flutter/flutter#141205) 2024-01-09 [email protected] Add environment variable to leak tracking bots. (flutter/flutter#141137) 2024-01-09 [email protected] Reapply "Dynamic view sizing" (#140165) (flutter/flutter#140918) 2024-01-09 [email protected] Introduce new Form validation method (flutter/flutter#135578) 2024-01-09 [email protected] Update `RouteObserver` example and fix an error thrown (flutter/flutter#141166) 2024-01-09 [email protected] Upgrade leak_tracker. (flutter/flutter#141153) 2024-01-09 [email protected] [ci.yaml] Do not run packaging test on presubmit (flutter/flutter#141192) 2024-01-09 [email protected] Roll Flutter Engine from 036b39fa47fa to a35e3b026e1d (6 revisions) (flutter/flutter#141191) 2024-01-09 [email protected] Run tests on iOS 16 or iOS 17 (flutter/flutter#141178) 2024-01-09 [email protected] Remove conditions that depend on order. (flutter/flutter#141183) 2024-01-09 [email protected] Roll Flutter Engine from b3c8597df0e2 to 036b39fa47fa (1 revision) (flutter/flutter#141179) 2024-01-09 [email protected] resolved the issue of indeterminate CircularProgressIndicator.adaptive on Darwin (flutter/flutter#140947) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
This PR fixes scrolling issues with
NestedScrollView
using theBouncingScrollPhysics
. In one of the steps of the calculation, we can reach a state where the position of the inner scrollable is set to adouble
value that falls withinprecisionErrorTolerance
of0
but we were using==
with0
rather than checking for a precision. My posts in the linked issue show the current behavior, and how I reached to conclusion (the code in this PR). This PR only addresses the "jumping" of the outer scrollable.Fixes #136199
Pre-launch Checklist
///
).I have not finished a test for this since I have never done so and therefore have 0 experience writing tests in Flutter, so any help there would be appreciated. I am also not sure how to test double precision errors in general. I did run all the nested_scroll_view_tests.dart locally and there are no failures.