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
Provide method and/or config to programmatically scroll to ListView index #12319
Comments
@Hixie is this a reasonable feature request? |
It's certainly a reasonable request... how easy it is to implement is a different matter. :-) For fixed-item-height list views it's easy to work around (just jump to the index * the height). For variable-height list views, it's really difficult in the current setup (because we don't know how far to scroll). It's the same thing that's blocking #10826. |
@Hixie please forgive my ignorance, but does it have to do with |
That's part of the code that makes sure that widgets that aren't visible aren't laid out, yes. And that's the reason we don't know the offset for the widgets that aren't visible. |
I have to add that I spent quite a few time in the past to figure out the fact that this feature is missing as I consider it being a critical requirement for a lot of common scenarios (chats, readers, contact lists just to name a few...) and for sure at least a couple of our apps. While I understand the complexity of an animated version of this feature, I thought that a non-animated |
another possible approach would be to be able to correctly estimate the height of the rows upfront and provide a correct offset to the |
In case of smooth scrolling, if it is 1 element visible and 1001 is requested, no need to scroll through all 1000 elements. |
This is definitely something we want to offer, we just haven't implemented it yet. The general case (animating to an item selected by index) is non-trivial, but we sort of need to know what our approach for that will be before we can design the API for the simpler cases as well. |
I made a small test app implementing ScrollToLine functionality, it should work also with mixed (different lineHeight) lists. The source: https://github.com/DmitryIvanitskiy/Animation/blob/master/main.dart
|
This was brought up in https://proandroiddev.com/quire-building-a-sophisticated-mobile-app-with-googles-flutter-2770065284d6 (from quire) just now. |
In many use cases jumpTo(_index) is critical, while scrollTo(_index) is unnecessary or even undesirable. If a user is in the middle of a long list, tapping to see the details and then coming back, scrolling all the way from the top to the desired position is a bad UX, whether it's manual or programmatic. I believe that jumpTo() is a major UX improvement in 100% of "coming back" use cases, while scrollTo is applicable only to a small subset of use cases. |
I am currently running into this. Working with Lists from a REST API and up to 500-100 items in each list and every time more are added future builder gets called and it scrolls to the top. then you have to scroll all the way to the bottom. |
This would be great for |
I'm implementing gallery of photos and have a button "scroll to chosen date when photo was made". So scrollToPosition also important for me. Calculating offset is not very accurate and on the long amount of data (2-4k photos) it's not right. And I could change the layout, so I would have to rewrite logic for calculating offset, especially to support changing orientation. |
I would also love to have this feature. As it stands, I'm not really sure of a great way to implement a chat app where the message list starts scrolled to the latest message, especially since not all rows will have the same height |
@CyanBlob set https://docs.flutter.io/flutter/dart-core/bool-class.html to |
@marica27 does the scroll position really need to reflect the exact position over all photos? |
@zoechi Along with datePicker feature I have a draggable scrollbar showing date next to it. Have you seen Google Photos app or in Samsung Gallery App? So I want the same. |
I don't follow. If you know the offset, then you can just scroll there like |
sorry for pure explanation. My list has 2 features. One is scroll to item with selected date and other is draggable scrollbar with label showing date for current position (as in google photos app). |
@zoechi I had tried setting |
@Hixie @zoechi The core of this problem is that |
@Hixie thanks for the response.
Why? I did it just fine in the sample code. If you have a data model, it is the definition of itemHeight, no calculation needed.
That should be represented in your data model so you can query it as well.
Why is that more efficient? What is the inefficiency in the proposed data model approach? |
In some cases you can't know what the height of an item is until you perform a layout of the item and take into account issues such as the space used for a particular font, line breaking of text, and the size of images, the latter of which might need to be downloaded from some remote source. Having your data source return the height of a item would mean the data source will need to do this layout (and would consequently need to know something about the dimensions of the viewport, such as needing to know the width of the viewport to work out line breaking). In the case of a long list, you could need to do the layout for thousands of items to compute the position of some items, leading to the expensive computations @Hixie refers to. |
@tarobins That would only be the case if you are displaying content that isn't known at build time and is in a form factor that isn't defined at build time and can't be spatially compressed. For example, showing user submitted images but you refuse to display them resized. Even in your text situation, the height of a widget is deterministic and should be able to be calculated. I don't know if we've surfaced the logic to the framework but there is definitely code in the engine that given a string and a font and a width, it will tell you the height of the space needed to render it completely. It isn't the slickest solution, but I don't think the problem is all that common either. A chat room app might be the only thing I could think of. Most people can determine the height of their widgets or design their widgets to render in a specified height. I know this because the original post asks why we can't do something that UITableView does, and that's because UITableView has a data model that looks similar to what I'm proposing. Without a data model, I dare say it's impossible to efficiently jump to a given item in a situation with heterogeneous children heights. The only solution there is to build and throw away all the proceeding widgets, which is almost in all cases going to be unacceptable. |
I'm not quite sure exactly what you mean by data model in this context. Do you mean a model that provides heights for the items or just a model of the data to be displayed? We've solved the jumping case without knowing the heights of the items in a data model and without building all the widgets by using the method @Hixie described. And example can be found here #12319 (comment) Smooth scrolling is a bit more complicated. There's one solution here https://github.com/google/flutter.widgets/tree/master/lib/src/scrollable_positioned_list |
For a ListView you want to display some state
That's an interesting approach but I think a solution that doesn't involve ScrollerController is kind of hacky in my opinion. Controlling where you are scrolled is raison-d-etre of ScrollerController.
It looks like this is caching the size of widgets, introspecting into the offset as widgets are created? It's a lot of code to accomplish something similar to what I did in 100 lines of code, just to avoid defining |
Even if you know what pixel offset to start the ScrollController at, or jump to, the current implementation of ListView will build and layout everything between the 0 offset and your desired offset in order to know what to put at the scroll offset your asked for, so, for long lists, using the ScrollController to position the list can be inefficient. |
@gaaclarke for an example where the ListView items are generated in such a way that the dimensions cannot be known statically: I'm working on an application that shows a list of tasks in a ListView. Each task has dynamic elements (mainly text widgets) that the user can configure, so I rely on Flutter's layout engine to determine the dimensions of the ListView items. I'm using a horizontal list view, where dynamic dimensions along the main axis are probably more common, but the same problem could arise for a vertical list of user-editable tasks. |
google/flutter.widgets#31 |
Tarobins, ScrollablePositionedList worked beautifully. Help me now add a header that appears when scrolling down and disappears when scrolling up. This is very useful for showing details of a certain book, as in the Bible. |
Yeah, SliverPersistentHeader doesn't work with ScrollablePositionedList nor the method from #12319 (comment).
It's possible SliverPersistentHeader might work with one of those when used within NestedScrollView, but I haven't tried yet. I'll give it a try today, but no promises I'll get anywhere.
google/flutter.widgets#32 is the relevant issue, though a subset solution of that issue might be more tractable in the short term.
…On Fri, Nov 29, 2019 at 8:42 AM oseiasmribeiro ***@***.***> wrote:
Tarobins, ScrollablePositionedList worked beautifully. Help me now add a
header that appears when scrolling down and disappears when scrolling up.
This is very useful for showing details of a certain book, as in the Bible.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#12319?email_source=notifications&email_token=ABFFHOO73V5GJQREQJA4ZHTQWFA6PA5CNFSM4D5DEY52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEFPIA6Q#issuecomment-559841402>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABFFHOIHHZ6JVKK5SN3QZ33QWFA6PANCNFSM4D5DEY5Q>
.
|
Thanks a lot already Tarobins. ScrollablePositionedList is working very well. Congratulations! |
I'm not super surprised. I'm just creating my experiment app, so I'll play around with it for a bit and see what's going on. |
Ok thanks. Please let me know if I succeed! |
So, first, I noticed that in general floating doesn't seem to work as I expected for NestedScrollView. I tried setting in the example from https://api.flutter.dev/flutter/widgets/NestedScrollView-class.html and the SliverAppBar didn't float as shown in SliverAppBar's docs. I didn't have high hopes to ScrollablePositionedList to work out of the box within a NestedScrollView, and in particular because in the example for NestedScrollView it is noted for its CustomScrollView
and that's not true of ScrollablePositionedList's internal CustomScrollView. Furthermore, ScrollablePositionedList does some magic with switching what CustomScrollView is displayed sometimes, which is likely to confuse NestedScrollView. Some work will be needed to support SliverAppBar within ScrollablePositionedList However, if all you care about is positioning an item at the top of the list when you display it, this worked surprisingly well:
|
Great! Thanks. This way I how get the index of scroll? I save him to back read the book where he left off. |
oh. that's can't be done with the above. hmmm. If the size of your content and screen never changes, you could just store the scroll offset https://api.flutter.dev/flutter/widgets/ScrollController/offset.html If you can do without a collapsing app bar, then you can just have a statically sized widget with your header above the ScrollablePositionedList, all laid out in a column. Then use the ScrollablePositionedList's itemPositionsListener to get the position of items in the list. otherwise, it's trickier. I really should try to support a SliverAppBar on ScrollablePositionedList. I've had that request a couple times. I'll try to find some time to work on it. There's a few non-obvious behaviours we need to spec out though, such as does using ItemScrollController.scrollTo and ItemScrollController.jumpTo affect the size of the app bar and how so. |
Ok. For now I go use Fixed Header, until you implement something similar in ScrollablePositionedList. Thank you so much for everything. |
I'm going to close this issue with ScrollablePositionedList https://github.com/google/flutter.widgets/tree/master/lib/src/scrollable_positioned_list available. I am still working on the library and there are some fixes already submitted to the internal google repo that should be pushed to the github repo soon. Please file additional bugs and feature requests here: https://github.com/google/flutter.widgets/issues |
This comment has been minimized.
This comment has been minimized.
I don't see a solution that can be used on ListView itself without making a mess of the API because there's a conflict between pixel-based and item-based scrolling. When we jump or scroll to a item that's far down a list, if we want to keep the pixel-based and item-based indices consistent, we'd need to layout every item before the desired item, which can be prohibitively expensive. |
This comment has been minimized.
This comment has been minimized.
I can understand that one would want a solution integrated with the existing ListView; however, I wasn't able to think of one that I thought would be workable and at the same time that I thought would be an acceptable change to the core ListView. I did create a solution that I thought got to the core of what was originally asked for in this issue. I know there are still some desired features. For example, I have seen the requests to have the ScrollablePositionedList work with a collapsible appbar, unfortunately I haven't had time to explore a solution to that use case. (More requests can be seen or added at https://github.com/google/flutter.widgets/issues, and people are encouraged to fork my solution and submit PRs, or just create new solutions based on mine or from scratch). If you have use cases not covered, please open a new issue (perhaps with a linking comment from here so people interested see the new issue), with an exact explanation of not-yet-covered needs and use cases. Doing so will help someone provide solutions that meet the use cases you have. Also, if more documentation is needed for the solution I provided, please let me know, and I’ll work on providing updates, as I do want people to be able to use it. As for this issue, given that I am the current assignee of the issue, I didn’t want to leave the issue open, and give the impression that I was still working on the issue past the solution I was able to come up with. However, if someone does want to continue to work on integrating a solution with ListView, I'm happy to hand over this issue and they can reopen it. However, if no one has a feasible change to ListView in mind, I'm not sure leaving this issue open is useful, as doing so might give people an incorrect impression that a change to ListView is being worked on, or eventually will be worked on at some point in the reasonable future. If such a change is not foreseeable, it might be best to direct energies to coming up with new widgets that meet peoples’ use cases, which, personally, I think is the more obtainable path. |
@tarobins However, it would be great if this widget could have its own package in pub/dev, instead of being bundled with other widgets. That's totally non-standard. I am guilty of doing that myself (https://pub.dev/packages/assorted_layout_widgets) but I think ScrollablePositionedList is just too important to be buried into a package called flutter.widgets. |
exciting news! ScrollablePositionedList is now available in its own package on pub: https://pub.dev/packages/scrollable_positioned_list Please start pointing to that package. |
Thanks particularly to @mehmetf |
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 |
The ListView is successful at displaying large lists, however in some circumstances, such as a reader application it is useful to be able to focus to a certain list item offset, the iOS
UITableView
has- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
and on Android theListView
has eithersetSelection(index);
orsmoothScrollToPosition(index)
. Please can you add this feature?The text was updated successfully, but these errors were encountered: