Open andreyeurope opened 5 years ago
Doing something as general as what you request is going to be difficult. If you can tell me more, even in a email robinsontom at google, I might be able to suggest something.
Sorry for the delay.
Thanks for answering, Tom. I would like to keep the conversation here, as it might help other people as well. So I am working on a feature (no deadline) which will allow the users of my future app to save the location of an article (an article being in fact an HTML document parsed as a list of widgets) without knowing the size of the device and keep that location in sync on all devices own by the user (via Firestore). This is the main reason why I would like to know the index of the first visible element of the list.
Do you need to have the list appearing alongside other slivers within the CustomScrollView? If not, then I think CustomScrollView will already do what you want.
There's an example here https://github.com/google/flutter.widgets/blob/6779a6512be4686b9d801367efb473128f331be4/example/scrollable_positioned_list/lib/scrollable_positioned_list_example.dart#L120 that figures out what the first visible item in a list is.
If you have a list plus other types of slivers in a CustomScrollView, ScrollablePositionedList does not handle that case and doing so will be a bunch more work, the scale of which I'm not certain of at the moment.
If this isn't making sense, or I'm misunderstanding what you are looking for, some sample code of what you're trying to do might help.
You are right indeed. I need the list to appear alongside other slivers. For now, I only have a SliverAppBar and the SliverList, but in the future there will be other slivers as well.
The problem is that I tried thinking of different approaches, but all entail having some mechanism that tells me what index does the topmost visible element have and another mechanism for scrolling (or initializing the controller) to a specific index.
So, I doubt I'll get ScrollablePositionedList to work within a CustomScrollView. I think supporting a SliverAppBar (or a similar custom widget) at the top of a ScrollablePositionedList might be doable. Are there other use cases you've come across so far; other types of slivers you want to use along side the ScrollablePositionedList?
No, not in my case at least. The UI is basically a navigation bar and a list of widgets, which are the SliverChildDelegate and SliverAppBar widgets. It would be nice to still be able to choose the behavior of the app bar, like floating, pinned and snap,
I totally need this. I'm currently putting a ScrollablePositionedList inside a Column, not sure if I can do ListView.
I also want to do ScrollablePositionedList inside a ScrollablePositionedList.
Does a ListView inside a ListView work?
I think NestedListView inside a ListView could work. I ended up using my original structure which was CustomScrollView with SliverList with ListView and then something like.
because I couldn't get Scrollable.ensureVisible
to work correctly I don't know why 😭
Page Widget, where _scrollie
is my ScrollController
void scrollToOffset(double offset) {
var y = offset + _scrollie.position.pixels;
_scrollie.animateTo(
y,
duration: Duration(milliseconds: 250),
curve: Curves.ease,
);
}
Card Widget
RenderBox box = context.findRenderObject();
var position = box.globalToLocal(Offset.zero); // Gives you the position of the card relative to the current scroll position
scrollToOffset(position.dy);
Hi @tarobins,
I need this feature in production. Now I am scrolling the old fashioned way: CustomScrollView with pixel jumping. Not really helpfull. And we have to use CustomScrollView because we need the parallax effect inside the flexibeBar of SliverAppBar + a simple SliverList. When we have now for example an: SliverPositionedList. It would be awesome 💪🏼. Then you would just pass inside SliverPositionedList the itemScrollController and we would break up the work into just one simple Sliver Component :)
Hope this will come one day ❤️
Thx.
Hi @tarobins,
I need this feature in production. Now I am scrolling the old fashioned way: CustomScrollView with pixel jumping. Not really helpfull. And we have to use CustomScrollView because we need the parallax effect inside the flexibeBar of SliverAppBar + a simple SliverList. When we have now for example an: SliverPositionedList. It would be awesome 💪🏼. Then you would just pass inside SliverPositionedList the itemScrollController and we would break up the work into just one simple Sliver Component :)
Hope this will come one day ❤️
Thx.
Totally Agree !!!
If there are SliverPositionedList and SliverPositionedGird that can fast jump or animate to the item position or PositionedCustomScrollView that can jump or animate to sliver widget start position, it will really help!
And as the scroll view is more and more complicated now and in the future, the NestedScrollView and CustomScrollView may be more commonly used than ListView and GridView.
Hi guys, I found this package on StackOverflow, it works with CustomScrollView. https://stackoverflow.com/a/61709995/2888623 https://pub.dev/packages/scroll_to_index
This is a not a problem in ScrollablePositionedList but in the SliverFillRemaining. If you set up physics in ScrollablePositionedList to NeverScrollableScrollPhysics() it works perfectly fine, until you realize the end of the list have been cut off depending the your device's screen height. I feel I am very close to solving it. if you set the SliverFillRemaining to has scrollable body. you'll get the error: LayoutBuilder does not support returning intrinsic dimensions. if you rap it with a container the extra height will be a problem and the the position of the first and last items will all be messed up. I think the easiest way is for the flutter team to create a bool option in SliverFillRemaining to assume the device's screen has an infinite height, which will allow our list to appear in full. I think the error is more in SliverFillRemaining rather than ScrollablePositionedList. I think this stack kind of addressed part of the problem.
If someone has found a solution please let us know it's very important for my app. I would like to add that there might be another sliver widget that can solve it for me instead of ScrollablePositionedList, however I since my list is dynamically built I am not sure about the height before building.
I believe the last piece of the puzzle is to figure out how to edit the scrollExtent and paintExtent SliverGeometry for the SliverFillRemaining. If there is a way to customize it. It would be great if anyone can figure it out
@Piinks & @bkonyi , since you both worked on it(https://github.com/flutter/flutter/pull/47379) can you please help us. Thank you
@hassanfaour sorry, but I'm not familiar with flutter/flutter#47379.
I just realized my analysis was wrong Increasing the max extend and scroll extend ruined the scroll position reader. If someone is interested in seeing what I did. I used this instead of sliver fill remaining:
class _SliverFillRemainingWithScrollable extends SingleChildRenderObjectWidget { const _SliverFillRemainingWithScrollable({ Key key, Widget child, }) : super(key: key, child: child);
@override RenderSliverFillRemainingWithScrollable createRenderObject( BuildContext context) => RenderSliverFillRemainingWithScrollable(); }
class RenderSliverFillRemainingWithScrollable extends RenderSliverSingleBoxAdapter { /// Creates a [RenderSliver] that wraps a scrollable [RenderBox] which is /// sized to fit the remaining space in the viewport. RenderSliverFillRemainingWithScrollable({RenderBox child}) : super(child: child);
@override void performLayout() { final SliverConstraints constraints = this.constraints; // TODO(Piinks): This may fill too much space for NestedScrollView, https://github.com/flutter/flutter/issues/46028 final double extent = constraints.remainingPaintExtent - math.min(constraints.overlap, 0.0);
if (child != null)
child.layout(constraints.asBoxConstraints(
minExtent: extent,
maxExtent: extent + 10000,
));
final double paintedChildSize =
calculatePaintOffset(constraints, from: 0.0, to: extent);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = SliverGeometry(
scrollExtent: paintedChildSize + 500,
paintExtent: paintedChildSize,
maxPaintExtent: paintedChildSize,
hasVisualOverflow: extent > constraints.remainingPaintExtent ||
constraints.scrollOffset > 0.0,
);
if (child != null) setChildParentData(child, constraints, geometry);
} }
SliverFillRemaining is intended by default to contain a scrollable. It is used as part of the 'inner' scrollable to create the NestedScrollView widget. SliverFillRemaining.hasScrollBody is true by default.
The NestedScrollView widget handles a lot of the other eccentricities of nested scroll views, which sounds like the pain points that are being experienced here. Placing a ScrollablePositionedList inside of a CustomScrollView is nested scrolling. Have you considered trying the NestedScrollView widget?
I also ran into this problem, and I can confirm a NestedScrollView
widget does work! I am using a SliverAppBar
in the headerSliverBuilder
and ScrollablePositionedList
in the body.
Thank you @Piinks
@wwwdata with only SliverAppBar in headerSliverBuilder it make sense, but not working if there are more than one widget in headerSliverBuilder, you can't have same controller to control both NestedScrollView and ScrollablePositionedList to move consistently...
Hi @tarobins
I'm also facing issue, I need to use CupertinoSliverRefreshControl() so, i'm using CustomScrollView() and inside CustomScrollView() i need use initialScrollIndex so, i'm using ScrollablePositionedList.builder(). If i click any item in that, it is navigating to that index(that item) but getting white screen and there is no exception in the terminal.
CustomScrollView(
slivers: [
CupertinoSliverRefreshControl(
onRefresh: refreshList,
),
SliverList(delegate: SliverChildBuilderDelegate((context, index) {
return Scrollbar(
child: ScrollablePositionedList.builder(
/******/
);
}))
],
)
I also ran into this problem, and I can confirm a
NestedScrollView
widget does work! I am using aSliverAppBar
in theheaderSliverBuilder
andScrollablePositionedList
in the body.Thank you @Piinks
I have been trying to come up with a work around for this issue. I was using a NestedScrollView with the ScrollablePositionedList in the body as well. You can pass a scroll controller to the NestedScrollView and then pass the same controller to the Widget that has your ScrollablePositionedList then listen to the scrollOffsetListener and use it to manually expand and collapse the NestedScrollView SliverAppBar. Granted its not the best of solutions but if you are on a time sensitive task it will work for the mean time as we wait for the Flutter Team to come up with a handy solution. Should be any day now 🤕
One more vote for adding something like SliverAppBar to ScrollablePositionedList. Thanks! That is all.
It is really important to add SliverAppBar to ScrollablePositionedList. Why has there been no progress?
It would be awesome to be able to use ScrollablePositionedList inside a CustomScrollView. I am currently working on a MVP that uses Slivers for reading some content, and by using ScrollablePositionedList with another library, I would be able to save the position inside the content when the user has left the page on any device.