Detecting UIScrollView page change
Use this to detect which page is currently being shown and perform some action on page change:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
static NSInteger previousPage = 0;
CGFloat pageWidth = scrollView.frame.size.width;
float fractionalPage = scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
if (previousPage != page) {
// Page has changed, do your thing!
// ...
// Finally, update previous page
previousPage = page;
}
}
If it's acceptable for you to only react to the page change once the scrolling has completely stopped, then it would be best to do the above inside the scrollViewDidEndDecelerating:
delegate method instead of the scrollViewDidScroll:
method.
In paging enabled scroll view you can use scrollViewDidEndDecelerating to know when the view is settled on a page (might be the same page).
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
scrollViewDidScroll
gets called on every movement. And in context of paging enabled view can be used to find when it is scrolled enough to move to next page (if dragging is stopped at that point).
How about combining two methods of UIScrollViewDelegate?
In scrollViewDidEndDragging(_:willDecelerate:)
, if it stops right away, we do the page calculation; if it is decelerating, we let it go and it will be caught by scrollViewDidEndDecelerating(_:)
.
The code is tested with XCode version 7.1.1, Swift version 2.1
class ViewController: UIViewController, UIScrollViewDelegate {
// MARK: UIScrollViewDelegate
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if decelerate == false {
let currentPage = scrollView.currentPage
// Do something with your page update
print("scrollViewDidEndDragging: \(currentPage)")
}
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let currentPage = scrollView.currentPage
// Do something with your page update
print("scrollViewDidEndDecelerating: \(currentPage)")
}
}
extension UIScrollView {
var currentPage: Int {
return Int((self.contentOffset.x+ (0.5*self.frame.size.width))/self.frame.width)+1
}
}