Tell When a UIPageViewController is Scrolling (for Parallax Scrolling of an Image)

僤鯓⒐⒋嵵緔 提交于 2019-11-28 17:14:50
Pavel Gurov
for (UIView *view in self.pageViewController.view.subviews) {
    if ([view isKindOfClass:[UIScrollView class]]) {
         [(UIScrollView *)view setDelegate:self];
    }
} 

this gives you access to all standard scroll view API methods. And this is not using private Apple API's.

I added traversing through subviews, to 100% find the UIPageViewController's inner scroll view WARNING: Be careful with scrollview.contentOffset. It resets as the controller scrolls to new pages

If you need persision scrollview offset tracking and stuff like that, it would be better to use a UICollectionViewController with cells sized as the collection view itself and paging enabled.

I would do this:

Objective-C

for (UIView *v in self.pageViewController.view.subviews) {
    if ([v isKindOfClass:[UIScrollView class]]) {
        ((UIScrollView *)v).delegate = self;
    }
}

and implement this protocol

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

Swift

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

and implement this protocol

func scrollViewDidScroll(scrollView: UIScrollView)

My guess is that it is not a UIPageViewController, but rather a paged UIScrollView. The UIScrollView does give you a constantly repeated delegate method that tracks what is happening as the scrolling takes place.

Alternatively, you might be able to access the paged UIScrollView that the UIPageViewController is secretly using, but you might break something, and I'm not sure how Apple would feel about it.

Use @Paul's snippet -

for (UIView *v in self.pageViewController.view.subviews) {
if ([v isKindOfClass:[UIScrollView class]]) {
    ((UIScrollView *)v).delegate = self;
}
}

to implement this protocol : -(void)scrollViewDidScroll:(UIScrollView *)scrollView

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGPoint point = scrollView.contentOffset;

float percentComplete;
percentComplete = fabs(point.x - self.view.frame.size.width)/self.view.frame.size.width;
NSLog(@"percentComplete: %f", percentComplete);
}

This gives you the percentage completion of the scroll. Happy coding!

extension UIPageViewController {

    var scrollView: UIScrollView? {

        return view.subviews.filter { $0 is UIScrollView }.first as? UIScrollView
    }
}

Using:

pageController.scrollView?.delegate = self

In Swift 3 you could write it even shorter:

if let scrollView = self.pageViewController.view.subviews.first(where: { $0 is UIScrollView }) as? UIScrollView {
    scrollView.delegate = self
}

What you are looking for is called parallax scrolling, you can find several libraries that can help you with that.

Edit: Matt is right this is not an answer, only a hint. Anyway let's complete it:

For animating a background image that lay behind your UIPageViewController you should use the delegate methods that it offer:

-[id<UIPageViewControllerDelegate> pageViewController:willTransitionToViewControllers:]
-[id<UIPageViewControllerDelegate> pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:]

With these two methods you can calculate the percentage of the scrolling (you should store your controllers in your array to know at which controller you scrolled to and get the percentage)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!