How to know exactly when a UIScrollView's scrolling has stopped?
I found a solution:
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
I did not notice that last bit before, willDecelerate
. It is false when the scrollView is stationary when ending the touch. Combined with the above-mentioned speed check, I can snap both when it's slow (and not being touched) or when it's stationary.
For anyone not doing any snapping but needs to know when scrolling stopped, didEndDecelerating
will be called at the end of the scroll movement. Combined with a check on willDecelerate
in didEndDragging
, you'll know when the scrolling has stopped.
[Edited Answer] This is what I use - it handles all the edge cases. You need an ivar to keep state, and as shown in the comments, there are other ways to handle this.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
//[super scrollViewWillBeginDragging:scrollView]; // pull to refresh
self.isScrolling = YES;
NSLog(@"+scrollViewWillBeginDragging");
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
//[super scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; // pull to refresh
if(!decelerate) {
self.isScrolling = NO;
}
NSLog(@"%@scrollViewDidEndDragging", self.isScrolling ? @"" : @"-");
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
self.isScrolling = NO;
NSLog(@"-scrollViewDidEndDecelerating");
}
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
{
self.isScrolling = NO;
NSLog(@"-scrollViewDidScrollToTop");
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
self.isScrolling = NO;
NSLog(@"-scrollViewDidEndScrollingAnimation");
}
I created a really simple project uses the above code, so that when a person interacts with a scrollView (including a WebView), it inhibits process intensive work until the user stops interacting with the scrollView AND the scrollview has stopped scrolling. It's like 50 lines of code: ScrollWatcher
Here's how to combine scrollViewDidEndDecelerating
and scrollViewDidEndDragging:willDecelerate
to perform some operation when scrolling has finished:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self stoppedScrolling];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
[self stoppedScrolling];
}
}
- (void)stoppedScrolling
{
// done, do whatever
}