Reputation: 6082
I'm using a ScrollController
for a SingleChildScrollView
widget where I want to detect scroll start, scroll end/stop and still scrolling.
How can I detect this?
I'm using Listener
scrollController = ScrollController()
..addListener(() {
scrollOffset = _scrollController.offset;
});
Also try with _scrollController.position.activity.velocity
but didn't help me.
Also there are
_scrollController.position.didEndScroll();
_scrollController.position.didStartScroll();
But how can I use it?
Upvotes: 46
Views: 74668
Reputation: 116
I created an extension to make things easier:
import 'package:flutter/widgets.dart';
extension ScrollControllerExtension on ScrollController {
void addScrollEndListener(VoidCallback onScrollEnd) {
addListener(() {
if (position.pixels == position.maxScrollExtent) {
onScrollEnd();
}
});
}
}
and the usage is:
final _scrollController = ScrollController();
@override
void initState() {
super.initState();
_scrollController.addScrollEndListener(
() {
fetchMore();
},
);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
Upvotes: 1
Reputation: 141
update 2023 : to check scroll stop after scrolling
if(notification.direction == ScrollDirection.idle)
Upvotes: 0
Reputation: 1779
There's a package for this use case. scroll_edge_listener
You can detect either the start or the end of the scroll with a few configurations such as offset and debounce. Just wrap your scroll view with the ScrollEdgeListener
and attach a listener.
ScrollEdgeListener(
edge: ScrollEdge.end,
edgeOffset: 400,
continuous: false,
debounce: const Duration(milliseconds: 500),
dispatch: true,
listener: () {
debugPrint('listener called');
},
child: ListView(
children: const [
Placeholder(),
Placeholder(),
Placeholder(),
Placeholder(),
],
),
),
Upvotes: 0
Reputation: 777
You can use _scrollController.position.pixels
for getting scroll position and addlistener
to be notified about changes
if(_scrollController.position.pixels == _scrollController.position.maxScrollExtent){
//for scroll end
}
if(_scrollController.position.pixels == _scrollController.position.minScrollExtent){
//for scroll at top
}
Upvotes: 2
Reputation: 1183
No need for NotificationListener
, we can use solely scroll controller for this.
First, register a post-frame callback by using WidgetsBinding.instance.addPostFrameCallback
to make sure that the scroll controller by that time has already associated with a scroll view. We will setup listener in that callback.
For listening to scrolling update we can use scrollController.addListener
.
For listening to start and stop scrolling we can use bgScrollCtrl.position.isScrollingNotifier.addListener
. You can check the code below:
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
scrollCtrl.addListener(() {
print('scrolling');
});
scrollCtrl.position.isScrollingNotifier.addListener(() {
if(!scrollCtrl.position.isScrollingNotifier.value) {
print('scroll is stopped');
} else {
print('scroll is started');
}
});
});
Upvotes: 67
Reputation: 1481
NotificationListner not work for me because i animate scrollview. When i touch it ScrollEndNotification is called.
So to detect scrollview reach bottom or top. I added Listner to scrollcontroller.
_scrollController.addListener(_scrollListener);
_scrollListener() {
if (_scrollController.offset >= _scrollController.position.maxScrollExtent &&
!_scrollController.position.outOfRange) {
setState(() {
debugPrint("reach the top");
});
}
if (_scrollController.offset <= _scrollController.position.minScrollExtent &&
!_scrollController.position.outOfRange) {
setState(() {
debugPrint("reach the top");
});
}
}
Upvotes: 3
Reputation: 47049
From this link https://medium.com/@diegoveloper/flutter-lets-know-the-scrollcontroller-and-scrollnotification-652b2685a4ac
Just Wrap your SingleChildScrollView
to NotificationListener
and update your code like ..
NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification is ScrollStartNotification) {
_onStartScroll(scrollNotification.metrics);
} else if (scrollNotification is ScrollUpdateNotification) {
_onUpdateScroll(scrollNotification.metrics);
} else if (scrollNotification is ScrollEndNotification) {
_onEndScroll(scrollNotification.metrics);
}
},
child: SingleChildScrollView(
/// YOUR OWN CODE HERE
)
)
And just declare method like
_onStartScroll(ScrollMetrics metrics) {
print("Scroll Start");
}
_onUpdateScroll(ScrollMetrics metrics) {
print("Scroll Update");
}
_onEndScroll(ScrollMetrics metrics) {
print("Scroll End");
}
You will be notify by particular method.
Upvotes: 59
Reputation: 1580
_scrollController.position.pixels
if(_scrollController.position.pixels == _scrollController.position.maxScrollExtent){
//scroll end
}
to use these, you should add a listener to your scrollview
Upvotes: 5