Repository navigation
Description
Hello there!
Right now a ScrollPhysics is only updated if you change the class type.
flutter/packages/flutter/lib/src/widgets/scrollable.dart
Lines 458 to 463 in f82046b
| bool _shouldUpdatePosition(Scrollable oldWidget) { | |
| ScrollPhysics? newPhysics = widget.physics ?? widget.scrollBehavior?.getScrollPhysics(context); | |
| ScrollPhysics? oldPhysics = oldWidget.physics ?? oldWidget.scrollBehavior?.getScrollPhysics(context); | |
| do { | |
| if (newPhysics?.runtimeType != oldPhysics?.runtimeType) | |
| return true; |
I think it would be great to follow some other patterns inside the flutter framework to allow this class to be reactive. This would be to add a new method inside the ScrollPhysics like
bool shouldReload (covariant ScrollPhysics old) => false;Notice by default would return false, so the behaviour for all the current ScrollPhysics would be the same as now.
Then when the Scrollable widget updates we would add
if (newPhysics?.runtimeType != oldPhysics?.runtimeType ||
newPhysics?.shouldUpdate(oldPhysics!))
return true;This pattern can be seen in LocalizationsDelegate, SliverPersistentHeaderDelegate, SliverChildDelegate, ScrollBehavior, and many more. (In the search box from the api website write should to see the rest)
Use case
I am building a ScrollPhysics that allows snapping to different positions if the scrollOffset is too close (Similiar to PageScrollPhysics). This would be very useful for SliverAppBars to accomplish this behaviour, where it only snaps to a expanded/collapsed state, but the scroll can not stop in the middle.
RPReplay_Final1617891051.MP4
It works, but right now it is not reactive. People need to do a hot-restart to see the changes made to it.
CustomScrollView(
physics: SnapScrollView(offset: 64, range: 20),
slivers: [
....
]
);It is important to consider this comment from the Scrollable doc though.
flutter/packages/flutter/lib/src/widgets/scrollable.dart
Lines 142 to 155 in f82046b
| /// The physics can be changed dynamically, but new physics will only take | |
| /// effect if the _class_ of the provided object changes. Merely constructing | |
| /// a new instance with a different configuration is insufficient to cause the | |
| /// physics to be reapplied. (This is because the final object used is | |
| /// generated dynamically, which can be relatively expensive, and it would be | |
| /// inefficient to speculatively create this object each frame to see if the | |
| /// physics should be updated.) | |
| /// | |
| /// See also: | |
| /// | |
| /// * [AlwaysScrollableScrollPhysics], which can be used to indicate that the | |
| /// scrollable should react to scroll requests (and possible overscroll) | |
| /// even if the scrollable's contents fit without scrolling being necessary. | |
| final ScrollPhysics? physics; |
I don't understand why it would be needed to create this object for each frame to see if has changed its configuration. Right now the type runtime is compared only when the widget or its dependencies are updated. So I think it would be the same to also check it through a shouldUpdate method if the configuration has changed.
Notice the ScrollPhysics class is immutable so it should not change its configuration after created. And when it changes didDependenciesUpdate or didWidgetUpdate should be triggered if is used in that scrollable.
cc: @Piinks
Activity
appinteractive commentedon Oct 18, 2021
@jamesblasco any progress or workaround on that issue?
jamesblasco commentedon Jan 21, 2022
As you can see I did not get any response about it 😅
Make ScrollPhysics reactive by introducing shouldUpdate (flutter#189664)
github-actions commentedon Sep 10, 2026
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
flutter doctor -vand a minimal reproduction of the issue.