I’m trying to build a screen where two vertically stacked ListViews cause themselves to grow and shrink as a result of being scrolled. Here is an illustration:
The initial state is that both lists take up 50% of the top and bottom of the screen respectively. When the user starts dragging the top list downward (to scroll up) it will initially cause the list to expand to take up 75% of the screen before the normal scrolling behavior starts; when the user changes direction, dragging upwards (to scroll down), then as they get to the bottom of the list it will cause the list to shrink back up to only taking up 50% of the screen (the initial state).
The bottom list would work similarly, dragging up would cause the list to expand upwards to take up 75% of the screen before the normal scrolling behavior starts; when the user changes direction, dragging downwards (to scroll up), then as they get to the top of the list it will shrink back to 50% of the screen.
Here is an animation of what it should look like:
https://share.cleanshot.com/mnZhJF8x
My question is, what is the best widget combination to implement this and how do I tie the scrolling events with resizing the ListViews?
So far, this is as far as I’ve gotten:
Column(
children: [
SizedBox(
height: availableHeight / 2,
child: ListView(...)
),
Expanded(child: ListView(...)),
],
),
In terms of similar behavior, it appears that the CustomScrollView and SliverAppBar have some of the elements in scrolling behaving I’m going after but it’s not obvious to me how to convert that into the the two adjacent lists view I described above.
Any advice would be greatly appreciated, thank you!
3
Answers
hi Check this,
First, initialise two scroll controllers for two of your listviews. Then register a post-frame callback by using
WidgetsBinding.instance.addPostFrameCallback
to make sure that the scroll controller has been linked to a scroll view. Next, setup scroll listeners in that callback.To listen to scrolling update you can use
scrollController.addListener
. Then use if-else cases to catch the position of the scroll, if scroll position equals to maxScrollExtent then the user scrolled bottom and its the other way round for minScrollExtent. Check my edited implementation below:edit: refactored and maybe better version:
here is the older post:
so, here’s my shot on this. There might be a less complicated solution of course but I think it’s somewhat understandable. At least I’ve tried to comment good enough.
Let me know if it works for you.
I think it’s working okayish so far but supporting the "fling" effect – I mean the acceleration when users shoot the scrollable until simulated physics slows it down again – would be really nice, too.