I have a NestedScrollView
with a SliverAppBar
. The body of the NestedScrollView
is a widget with a CustomScrollView
with a SliverList
.
I want to get the offset from the ScrollController
that is given to the NestedScrollView
but it only gives me the offset until the SliverAppBar
is out of view, but after that the SliverList
continues to scroll but the ScrollController
doesn't give the offset.
NestedScrollView(
headerSliverBuilder: (_, __) => SliverAppBar(..),
body: RefreshIndicator(
child: CustomScrollView(..),
),
)
The CustomScrollView
will automatically use the PrimaryScrollController
provided by NestedScrollView
.
When a listener is attached to that scroll view, the listener will be called when the SliverAppBar
slides into view and out of view until the position.extentAfter
is equal to 0.0
and then it will not update at all, no matter how far you scroll down because the extentAfter
always remains at 0.0
.
How can you retrieve the scroll position of the CustomScrollView
inside of the NestedScrollView
?
It is important that PrimaryScrollController
is used because the ScrollController
should have the features of PrimaryScrollController
. Anyways, in order for the SliverAppBar
to work, i.e. it scrolling out of view with the content, the NestedScrollView
controller
parameter needs to match the CustomScrollView
controller
(or primary
) parameter somehow.
Here is a demo.
Any implementation that allows the content to be scrolled with PrimaryScrollController.of(context)
is fine.
Just note that the NestedScrollView
is required in order for the RefreshIndicator
to appear below the SliverAppBar
.
It seems to me that you will need to attach a NotificationListener<ScrollNotification>
to track the offset of your inner CustomScrollView
NestedScrollView(
controller: // PrimaryScrollController
headerSliverBuilder: (_, __) => SliverAppBar(..),
body: RefreshIndicator(
child: NotificationListener<ScrollNotification>(
child: CustomScrollView(..),
onNotification: (ScrollNotification scrollInfo) {
double customPixel = scrollInfo.metrics.pixels; // same as offset
return false;
},
)
)
)
So, as you mentioned, your NestedScrollView controller’s listener will only respond up to the height of the SliverAppBar
. And once that is out of view, the ScrollNotification
will kick in and start responding to the CustomScrollView
scrolling. Accomplished in two separate areas:
Note, you could attach another controller/listener to the inner CustomScrollView
, but that would go against this note: https://api.flutter.dev/flutter/widgets/NestedScrollView-class.html
return CustomScrollView( // The "controller" and "primary" members should be left // unset, so that the NestedScrollView can control this // inner scroll view. // If the "controller" property is set, then this scroll // view will not be associated with the NestedScrollView.
Maybe, I can help you!
Widget build(BuildContext context) {
return Scaffold(
body: NestendScrollView(
headerSliverBuilder: (BuildContext context, bool value) {
return <Widget>[
SliverAppBar(),
];
},
body: SafeArea(
child: Builder(
builder: (context) {
final _scr = PrimaryScrollController.of(context);
_scr.addListener(() {
if (_scr.position.pixels == _scr.position.maxScrollExtent) {
print('At DOWNW!!!');
}
});
return CustomScrollView(
controller: _scr,
slivers: <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context,
),
),
SliverList(
delegate: SliverChildListDelegate(
List.generate(100, (int index) {
return Text('ITEM -> $index');
}),
),
)
],
);
},
),
),
),
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With