UIPageViewController的进展

我想在页面滚动过程中从uipageviewcontroller收到更新。 我想知道在%的transitionProgress。 (当用户移动手指以获得另一个页面时,该值应该更新)。 我感兴趣的是从一个页面到另一个页面的animation进度,而不是整个页面的进度。

到目前为止我发现的是:

  • 有一个名为UICollectionViewTransitionLayout的类,它具有与我正在查找的属性“transitionProgress”相对应的属性。 可能uipageviewcontroller以某种方式实现这个方法?

  • 我可以在uipagecontroller上调用下面的方法,但是结果只有0!

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

在SWIFT中复制粘贴;)对我来说是完美的

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 = fabs(point.x - view.frame.size.width)/view.frame.size.width NSLog("percentComplete: %f", percentComplete) } } 

最后,我find了一个解决scheme,即使它可能不是最好的办法:

我首先像这样在scrollview上添加一个观察者:

 // 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]; 

而当观察者被称为:

 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); 

我很高兴我发现这个:-)

因为我认为滚动的function将永远保留,但内部实现可能会改变为滚动视图以外的东西,我发现下面的解决scheme(我还没有testing过,但仍然)

 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是这里的UIPageViewController ,而[-viewControllerForPage:]是一个返回给定页面的视图控制器的方法)

如果absolutePosition为0.0f,则显示第一个视图控制器,如果它等于1.0f,则显示第二个视图,等等…这可以在CADisplayLink连同委托方法和/或UIPanGestureRecognizer一起被重复UIPanGestureRecognizer以有效地了解UIPageViewController当前进度的UIPageViewController

编辑:使它适用于任何数量的视图控制器

用这个 –

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

来实现这个协议: -(void)scrollViewDidScroll:(UIScrollView *)scrollView

然后以这种方式使用@ xhist的代码(修改)

 -(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); } 

虽然Appgix的解决scheme起初似乎工作,我注意到,当用户平移UIPageViewControllerUIPageViewController举起手指,然后立即开始再次拖动,而“快照”animation尚未完成,然后再次举起他的手指(这将再次“回弹”), scrollViewDidScroll方法只在页面视图控制器完成animation时被调用。 对于进度计算,这意味着第二个平移产生连续的值,如0.11 ,但是当滚动视图alignment时,下一个进度值将是1.0 ,这导致我的其他滚动视图不同步。

为了解决这个问题,我现在正在听滚动视图的contentOffset键,这个键在这种情况下仍然是不断更新的。

基于Appgix解决scheme,我直接在我的'UIPageViewController'子类中添加这个。 (因为我只需要这个)

对于Swift 3:

 class MYPageViewControllerSubclass: UIPageViewController, UIScrollViewDelegate { override func viewDidLoad() { super.viewDidLoad() for subView in view.subviews { if subView is UIScrollView { (subView as! UIScrollView).delegate = self } } } // MARK: - Scroll View Delegate public func scrollViewDidScroll(_ scrollView: UIScrollView) { let point = scrollView.contentOffset var percentComplete: CGFloat percentComplete = fabs(point.x - view.frame.size.width)/view.frame.size.width NSLog("percentComplete: %f", percentComplete) } // OTHER CODE GOES HERE... }