superlistapp / super_sliver_list

Drop-in replacement for SliverList and ListView that can handle large amount of items with variable extents and reliably jump / animate to any item.
https://superlistapp.github.io/super_sliver_list/
MIT License
277 stars 15 forks source link

How to set initial Scroll Position #58

Open dkliss opened 3 months ago

dkliss commented 3 months ago

I have been using the scrollable_positioned_list and wanted to give a go to super_sliver_list. I have set this up and I have a function as below to jump to a specific item when first time list is built.

However, I see a rebound i.e. first the whole list is built, and then i am takin to correct index (as discussed in https://github.com/superlistapp/super_sliver_list/issues/35).

I was expecting that the list exactly points to the index I wanted the list to be at at the when a list is build. This is something similar to what we use in ScrollController(initialScrollOffset: item height index).But because I have variable heights, I cannot use ScrollController(initialScrollOffset: item height index).

What I was expecting is, that, there is a constructor parameter called "initialPosition", which when provided lets the SuperSilverList to set that as first position in ListController or Scroll Controller.

I was wondering if this is an issue or if I am doing anything not correct. Thanks for your help.

 void jumpToItem(int index) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      try {
        state.listController.jumpToItem(
          index: index,
          scrollController: state.scrollController,
          alignment: 0.5,
        );
      } catch (e) {
        // Handle the error (e.g., emit an error state)
        debugPrint('Error jumping to item: $e');
      }
    });
  }

And when i simply use function below, it does not work as (I suspect it require list to be build)


 void jumpToItem(int index) {

      try {
        state.listController.jumpToItem(
          index: index,
          scrollController: state.scrollController,
          alignment: 0.5,
        );
      } catch (e) {
        // Handle the error (e.g., emit an error state)
        debugPrint('Error jumping to item: $e');
      }
knopp commented 3 months ago

This is unfortunately tricky to do, because part of the process of jumping to index depends on RenderViewport.getOffsetToReveal, which assumes there already exists viewport instance and slivers. The reason for this is that the position doesn't only depends on the SuperSliverList itself, but there might be multiple SuperSliverLists in the viewport and they even may be nested in other slivers.

So the initialPosition on SuperSliverList could only work reliably when there are no other slivers in the list, which is not a great solution.

Alternative to this is indeed registering post frame callback, for example in the initState method of nearest state and doing the initial jump there. This does have a drawback of one frame delay, but depending on the application this might be acceptable and not too disruptive.

dkliss commented 3 months ago

Thanks you for quick response and confirmation!

Post framework call does work with but rebound issue, which does not fit my use case.

May be I need to combine this with some other package like scroll_to_index, which I can be used for initial position.

dkliss commented 3 months ago

Unfortunately, scroll_to_index suffer from same issue of rebound. So no luck with that.

knopp commented 3 months ago

Rebound? JumpToItem should not cause rebound in latest version (0.4.1). If it does it would be a bug. Can you provide a reproducible example with the rebound?

dkliss commented 3 months ago

The rebound occurs only when first time the list is build at init. Once build, the jumpTo works as expected. So this issue is only setting initial position, when first time list is build, where full list is laid out first and then jumpto is executed (in reversed list).

rayliverified commented 3 days ago

I'd like to add a +1 to this feature request. The existing set initial scroll position solutions are very bad.

jumpToItem isn't a good solution because it causes a first frame build of the initial items which causes stuttering. Frame 0: Items [0, 1, 2, 3, 4, 5, 6, 7, 8] are built.

JumpToItem(item 48) is called. Frame 1: Items [48, 49, 50, 51, 52, 53, 54] are built.

So the initialPosition on SuperSliverList could only work reliably when there are no other slivers in the list, which is not a great solution.

That's very much acceptable. ScrollController's current initialScrollOffset is intended as Flutter's solution for initial position but it doesn't solve anything and is pretty much useless.