Disable UIPageViewController bounce Disable UIPageViewController bounce ios ios

Disable UIPageViewController bounce


Disable UIPageViewController's bounce

  1. Add the <UIScrollViewDelegate> delegate to your UIPageViewController's header

  2. Set the UIPageViewController's underlying UIScrollView's delegates to their parent in viewDidLoad:

    for (UIView *view in self.view.subviews) {    if ([view isKindOfClass:[UIScrollView class]]) {        ((UIScrollView *)view).delegate = self;        break;    }}
  3. The implementation for scrollViewDidScroll is to reset the contentOffset to the origin (NOT (0,0), but (bound.size.width, 0)) when the user is reaching out of the bounds, like this:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {    if (_currentPage == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width) {        scrollView.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);    } else if (_currentPage == totalViewControllersInPageController-1 && scrollView.contentOffset.x > scrollView.bounds.size.width) {        scrollView.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);    }}
  4. Finally, the implementation for scrollViewWillEndDragging is to deal with a bug scenario when the user quickly swipes from left to right at the first page, the first page won't bounce at the left (due to the function above), but will bounce at the right caused by the (maybe) velocity of the swipe. And finally when bounced back, the UIPageViewController will trigger a page flip to the 2nd page (which is of course, not expected).

    - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {    if (_currentPage == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width) {        *targetContentOffset = CGPointMake(scrollView.bounds.size.width, 0);    } else if (_currentPage == totalViewControllersInPageController-1 && scrollView.contentOffset.x >= scrollView.bounds.size.width) {        *targetContentOffset = CGPointMake(scrollView.bounds.size.width, 0);    }}

Swift 4.0

Code to put into viewDidLoad:

for subview in self.view.subviews {    if let scrollView = subview as? UIScrollView {        scrollView.delegate = self        break;    }}

Implementation for scrollViewDidScroll:

func scrollViewDidScroll(_ scrollView: UIScrollView) {    if (currentPage == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width) {        scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0);    } else if (currentPage == totalViewControllersInPageController - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width) {        scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0);    }}

Implementation for scrollViewWillEndDragging:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {    if (currentPage == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width) {        targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0);    } else if (currentPage == totalViewControllersInPageController - 1 && scrollView.contentOffset.x >= scrollView.bounds.size.width) {        targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0);    }}


Disable UIPageViewController's bounce

Swift 2.2

Addition to answers

1) Add UIScrollViewDelegate to UIPageViewController

extension PageViewController: UIScrollViewDelegate

2) Add to viewDidLoad

for view in self.view.subviews {   if let scrollView = view as? UIScrollView {      scrollView.delegate = self   }}

3) Add UIScrollViewDelegate methods

func scrollViewDidScroll(scrollView: UIScrollView) {    if currentIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {        scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)    } else if currentIndex == totalViewControllers - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width {        scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)    }}func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {    if currentIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {        scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)    } else if currentIndex == totalViewControllers - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width {        scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)    }}


If you keep track of your currentIndex then the below should be sufficient but its a little buggy because there is a random scenario where it stops scrolling altogether.

I think the scrollView.bounces is a little buggy, perhaps I am missing something because most of the time it works fine, if anyone is able to have a solution based on the below it would be great please.

public func scrollViewDidScroll(_ scrollView: UIScrollView) {    scrollView.bounces = currentIndex == 0 ||        currentIndex == controllers.count - 1        ? false         : true}