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];
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)
}
}
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 :-)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With