opened
florisvdg
username_0
Use case: a ListView that supports loading in new items from the top and also from the bottom, like a Twitter timeline or an RSS feed. When dynamically adding new items at the bottom, everything is fine. However, when adding items from the top (in the case of a Twitter or RSS pull-to-refresh or a real time feed), the newly added items, from the perspective of the user, push the scroll position down, because the scroll content height has increased, resulting in a jump (or in the case of an AnimatedList: a slide animation). The user would just expect the scroll position to be at the same _item_ the user is looking at at that moment.

Because Flutter does not seem to have anything for this use case out of the box, a way to fix this issue is to just recalculate the scroll offset when the new items are added and then call `scrollController.jumpTo` upon an updated state. This is easy when you know the item size in advance. When the items have content dependent heights the calculation can be done using the previous `maxScrollExtent` and the new `maxScrollExtent`. However, when to then run this calculation seems to be a harder issue. 
I tried invoking it 
* right after `setState`, but that seems to be too early, because the `maxScrollExtent` is not known and not updated at that time
* using `WidgetsBinding.instance.addPostFrameCallback`, which works and sets the scroll offset to the desired position, but seems to do this too late, causing the scroll offset to quickly jump

Being able to listen for when the `maxScrollExtent` is actually updated could solve this issue. Or would there be an alternative way to do this? Seems like a pretty basic problem any serious social, twitter, news, rss app would run into.
ScrollController listenable maxScrollExtent
issue
created
zoechi
username_1
Related or similar #12319
comment
created
espedale
username_2
What is the status on the fix for this issue??? This makes my app look very clunky! Please provide a solution for this, Flutter!
comment
created
patelkrunal78
username_3
If you use a shrink-wrapped ListView with reverse: true, scrolling it to 0.0 will do what you want.

Full Code At [Here](https://icetutor.com/question/programmatically-scrolling-to-the-end-of-a-listview-2)
comment
created
tudor07
username_4
I am also impacted by this. It's a very common use case to add items to the top of a list. All possible workaround are not ideal because the list jumps around.

Any solution for this?
comment
created
gerry05
username_5
I'm making a chat room for multiple users and I'm having this problem. Please let me know if anyone has solved this issue. Thanks!
comment
created
esDotDev
username_6
+1, this would all be fixed by a getOffsetForIndex() API, which is sorely missing right now anyways. 

We really shouldn't need to measure previous and current extents in order to just jump to a specific index. If I was at index 0, and loaded 15 new items at the front if my list, I should simply be able to call **controller.jumpToIndex(15)** or **controller.jumpTo(controller.getOffsetForIndex(15))** to maintain scroll position.

Both would be nice :)
comment
created
tudor07
username_4
@username_1 any updates on this? it's been two years, I'm still struggling with this...
@username_0 did you fix this?
comment
created
florisvdg
username_0
I "fixed" it by shaping our requirements to allow for all list items to be of the same height...
comment
created
perclasson
username_7
This can done with a [CustomScrollView] and two slivers [SliverList]. You'll want to set the [CustomScrollView.center] to the key of the second sliver. Then whenever you content above the screen, add it to the first sliver, and when you want content below the second sliver.

I made an example: https://dartpad.dartlang.org/c3b9b03925cdaaf88c1b8fe78a3b96b0 I also reversed the slivers with [CustomScrollView.reverse] and added 1.0 to [CustomScrollView] to make sure that the initial content is correctly displayed.

@username_0 @username_4 Does this solution solve the problem for you? I'll go ahead and close the ticket unless you think otherwise.
comment
closed
perclasson
username_7
issue
created
gskinner-shared
username_8
While it solves this very specific use case, it does not address.the API limitation of scroll view that was the heart of the issue. Why not give us a simple event when maxExtents changes?
comment
reopened
perclasson
username_7
Use case: a ListView that supports loading in new items from the top and also from the bottom, like a Twitter timeline or an RSS feed. When dynamically adding new items at the bottom, everything is fine. However, when adding items from the top (in the case of a Twitter or RSS pull-to-refresh or a real time feed), the newly added items, from the perspective of the user, push the scroll position down, because the scroll content height has increased, resulting in a jump (or in the case of an AnimatedList: a slide animation). The user would just expect the scroll position to be at the same _item_ the user is looking at at that moment.

Because Flutter does not seem to have anything for this use case out of the box, a way to fix this issue is to just recalculate the scroll offset when the new items are added and then call `scrollController.jumpTo` upon an updated state. This is easy when you know the item size in advance. When the items have content dependent heights the calculation can be done using the previous `maxScrollExtent` and the new `maxScrollExtent`. However, when to then run this calculation seems to be a harder issue. 
I tried invoking it 
* right after `setState`, but that seems to be too early, because the `maxScrollExtent` is not known and not updated at that time
* using `WidgetsBinding.instance.addPostFrameCallback`, which works and sets the scroll offset to the desired position, but seems to do this too late, causing the scroll offset to quickly jump

Being able to listen for when the `maxScrollExtent` is actually updated could solve this issue. Or would there be an alternative way to do this? Seems like a pretty basic problem any serious social, twitter, news, rss app would run into.
ScrollController listenable maxScrollExtent
issue
created
HansMuller
username_9
@username_8 - as @username_0 pointed out, building a solution to this problem around reacting to the update of maxScrollExtent is tricky because the notification comes at layout time and ScrollController.jumpTo(), which - generally speaking - could trigger an additional layout, is going to affect the next frame.

The [solution suggested by @username_7](https://github.com/flutter/flutter/issues/21541#issuecomment-629121578) is relatively straightforward and nicely addresses this issue's use-case.

I think we should close this issue upon adding a version of the sample solution to the CustomScrollView API docs.
comment
created
esDotDev
username_6
It's a pretty common use case to need to know the accurate size of the scroll contents. Especially when building scrollbars. 

What we do now is basically hack around it using sheduleMicrotask, or create some system where the child tells us it's extent (via Notification or Callback). Seems like a proper event would at least be preferable to that?
comment
created
HickYeah
username_10
@username_7 , I would like to thank you so much for addressing this important topic. I've tried this with SliverAppBar and I couldn't maintain the right behavior as floating = true. 

how can I handle SliverAppBar on CustomScrollView in this example?
comment
created
HickYeah
username_10
Also, I would mention one more thing, I am currently using pull to refresh. when I implemented @username_7 approach I lost the trigger to pull and refresh
comment
created
HickYeah
username_10
@username_7  just FYI, I had some success in embedding SliverAppbar using NestedScrollViews but won't float because the issue  Support Floating+ SliverAppBars in NestedScrollViews #57707 

Still have an issue with a jump back to the top of the screen, because with the approach it won't 0.0 it goes with minimize, even using minScrollExtent won't get into all top.
comment
created
HickYeah
username_10
I was successfully able to jump to the top with 

 _scrollController.position.minScrollExtent - MediaQuery.of(context).size.height;

Actually, I don't the reason exactly just went further than the  minScrollExtent
comment
created
perclasson
username_7
@username_10 Looks like you manage to solve the issue!

Here is something similar to what you need, but with the solution of using two [SliverList]s: https://dartpad.dartlang.org/38a9320bb8edd30af3c8543c24df8a21

For future questions, I suggest asking in the discord/slack channel for Flutter, or create a new issue with your feature requests.
comment