How to detect when a UIScrollView has finished scrolling In Swift
Solution 1
The delegate method tells you when finished
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
self.stoppedScrolling()
}
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !decelerate {
self.stoppedScrolling()
}
}
func stoppedScrolling() {
println("Scroll finished")
}
Solution 2
The scrollViewDidEndDecelerating
won't be called if user is scrolling slowly. Here's Ashley Smart asnwear in Swift
func scrollViewDidScroll(_ scrollView: UIScrollView) {
NSObject.cancelPreviousPerformRequests(withTarget: self)
perform(#selector(UIScrollViewDelegate.scrollViewDidEndScrollingAnimation), with: nil, afterDelay: 0.3)
}
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
NSObject.cancelPreviousPerformRequests(withTarget: self)
// Call your function here
}
Solution 3
There is a method of UIScrollViewDelegate
which can be used to detect (or better to say 'predict') when scrolling has really finished:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
of UIScrollViewDelegate
which can be used to detect (or better to say 'predict') when scrolling has really finished.
In my case I used it with horizontal scrolling as following (in Swift 3):
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
perform(#selector(self.actionOnFinishedScrolling), with: nil, afterDelay: Double(velocity.x))
}
func actionOnFinishedScrolling() {
print("scrolling is finished")
// do what you need
}
Solution 4
You need to check whether the user has stopped dragging and if the view is still decelerating after the user stopped dragging:
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if collectionView.isDecelerating == false {
// Perform whichever function you desire for when scrolling has stopped
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// Perform whichever function you desire for when scrolling has stopped
}
Don Hall
Updated on November 25, 2021Comments
-
Don Hall over 2 years
There was, by all accounts, an excellent solution to this problem in Obj-C presented by Ashley Smart (How to detect when a UIScrollView has finished scrolling).
-(void)scrollViewDidScroll:(UIScrollView *)sender { [NSObject cancelPreviousPerformRequestsWithTarget:self]; //ensure that the end of scroll is fired. [self performSelector:@selector(scrollViewDidEndScrollingAnimation:) withObject:nil afterDelay:0.3]; ... } -(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { [NSObject cancelPreviousPerformRequestsWithTarget:self]; ... }
I need a solution, however, in Swift.
It appears that the excellent delay function, contributed by Matt (dispatch_after - GCD in swift?) is likely to help.
func delay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) }
and implemented as ...
delay(0.4) { // do stuff }
but I've still not put it together. Any help?
-
Bogdan about 7 yearsThis doesn't work in case the scroll has no deceleration towards the stop point, which may be very well when the user lifts his finger, so you may consider scrollViewDidEndDragging as well.
-
Bogdan about 7 yearsAnd even scrollViewDidEndScrollingAnimation, I didn't considered it earlier too :)
-
AmiguelS over 6 yearsWhat is the diference between checking
isDecelerating
vs checking the paramdecelerate
?