Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am trying to make an effect similar to that found in the new Yahoo weather app. Basically, each page in the UIPageViewController has a background image, and when scrolling through the page view, the Image's location only scrolls about half the speed. How would I do that? I thought I could use some sort of Delegate Method in the UIPageViewController to get the current offset and then update the images like that. The only problem is that I cannot find anyway to tell if the UIPageViewController is being scrolled! Is there a method for that? Thanks!

like image 266
Keiran Paster Avatar asked Apr 28 '13 21:04

Keiran Paster


6 Answers

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.

like image 94
Pavel Gurov Avatar answered Oct 19 '22 14:10

Pavel Gurov


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)
like image 26
Van Du Tran Avatar answered Oct 19 '22 12:10

Van Du Tran


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.

like image 3
matt Avatar answered Oct 19 '22 12:10

matt


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!

like image 3
genaks Avatar answered Oct 19 '22 14:10

genaks


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
}
like image 3
d.felber Avatar answered Oct 19 '22 12:10

d.felber


extension UIPageViewController {

    var scrollView: UIScrollView? {

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

Using:

pageController.scrollView?.delegate = self
like image 3
Mike Glukhov Avatar answered Oct 19 '22 14:10

Mike Glukhov