Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Progress of UIPageViewController

I would like to receive updates from the uipageviewcontroller during the page scrolling process. I want to know the transitionProgress in %. (This value should update when the user move the finger in order to get to another page). I'm interested in the animation progress from one page to another, not the progress through the total number of pages.

What I have found so far:

  • There is a class called UICollectionViewTransitionLayout that have the property corresponding to what I am looking for, "transitionProgress". Probably uipageviewcontroller implement this method somehow?

  • I can call the following method on the uipagecontroller but I only get 0 as result!

    CGFloat percentComplete = [self.pageViewController.transitionCoordinator percentComplete];

like image 654
Eric1101000101 Avatar asked Mar 22 '14 12:03

Eric1101000101


3 Answers

in SWIFT to copy paste ;) works perfect for me

extension UIPageViewController: UIScrollViewDelegate {

    public override func viewDidLoad() {
        super.viewDidLoad()

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

   public func scrollViewDidScroll(_ scrollView: UIScrollView) {
       let point = scrollView.contentOffset
       var percentComplete: CGFloat
       percentComplete = abs(point.x - view.frame.size.width)/view.frame.size.width
       print("percentComplete: ",percentComplete)
   }
}
like image 151
Appygix Avatar answered Nov 07 '22 03:11

Appygix


At last I found out a solution, even if it is probably not the best way to do it:

I first add an observer on the scrollview like this:

// Get Notified at update of scrollview progress
NSArray *views = self.pageViewController.view.subviews;
UIScrollView* sW = [views objectAtIndex:0];
[sW addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:NULL];

And when the observer is called:

NSArray *views = self.pageViewController.view.subviews;
UIScrollView* sW = [views objectAtIndex:0];
CGPoint point = sW.contentOffset;

float percentComplete;
//iPhone 5
if([ [ UIScreen mainScreen ] bounds ].size.height == 568){
    percentComplete = fabs(point.x - 568)/568;

} else{
//iphone 4
    percentComplete = fabs(point.x - 480)/480;
}
NSLog(@"percentComplete: %f", percentComplete);

I'm very happy that I found this :-)

like image 34
Eric1101000101 Avatar answered Nov 07 '22 01:11

Eric1101000101


Since I thought that the functionality of scrolling would stay forever, but that the internal implementation may change to something other than a scroll view, I found the solution below (I haven't tested this very much, but still)

NSUInteger offset = 0;
UIViewController * firstVisibleViewController;
while([(firstVisibleViewController = [self viewControllerForPage:offset]).view superview] == nil) {
  ++offset;
}
CGRect rect = [[firstVisibleViewController.view superview] convertRect:firstVisibleViewController.view.frame fromView:self.view];
CGFloat absolutePosition = rect.origin.x / self.view.frame.size.width;
absolutePosition += (CGFloat)offset;

(self is the UIPageViewController here, and [-viewControllerForPage:] is a method that returns the view controller at the given page)

If absolutePosition is 0.0f, then the first view controller is shown, if it's equal to 1.0f, the second one is shown, etc... This can be called repeatedly in a CADisplayLink along with the delegate methods and/or UIPanGestureRecognizer to effectively know the status of the current progress of the UIPageViewController.

EDIT: Made it work for any number of view controllers

like image 2
Stéphane Copin Avatar answered Nov 07 '22 02:11

Stéphane Copin