UIPageViewController的进展

时间:2014-03-22 12:59:30

标签: ios uipageviewcontroller transitions

我想在页面滚动过程中从uipageviewcontroller接收更新。我想知道%的transitionProgress。 (当用户移动手指以进入另一页时,此值应更新)。我对从一个页面到另一个页面的动画进度感兴趣,而不是通过总页数进展。

到目前为止我发现了什么:

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

  • 我可以在uipagecontroller上调用以下方法,但结果只得到0!

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

7 个答案:

答案 0 :(得分:16)

在SWIFT中复制粘贴;)非常适合我

{{1}}

答案 1 :(得分:4)

最后我发现了一个解决方案,即使它可能不是最好的方法:

我首先在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);

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

答案 2 :(得分:2)

由于我认为滚动的功能会永远存在,但内部实现可能会改变为滚动视图以外的其他内容,我在下面找到了解决方案(我还没有对此进行过多次测试,但仍然)

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,则显示第二个,等等......这可以在{ {1}}以及委托方法和/或CADisplayLink有效地了解UIPanGestureRecognizer当前进度的状态。

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

答案 3 :(得分:2)

使用此 -

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

答案 4 :(得分:1)

虽然Appgix的解决方案一开始似乎有用,但我注意到当用户平移UIPageViewController时,很快抬起手指然后立即开始再次拖动,而“快照”动画还没有结束然后再次抬起手指(这将再次“快速恢复”),仅在页面视图控制器完成动画时调用scrollViewDidScroll方法。 对于进度计算,这意味着第二个平移会生成连续值,例如0.110.130.16,但当滚动视图快照时,下一个进度值将为1.0,这会导致我的其他滚动视图不同步。

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

答案 5 :(得分:0)

基于Appgix解决方案,我直接在我的' 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...

}

答案 6 :(得分:0)

Swift 4的KVO方法

var myContext = 0

override func viewDidLoad() {
    for view in self.view.subviews {
        if view is UIScrollView {
            view.addObserver(self, forKeyPath: "contentOffset", options: .new, context: &introPagingViewControllerContext)
        }
    }
}

// MARK: KVO

override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?,
                           change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?)
{
    guard let change = change else { return }
    if context != &myContext {
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        return
    }

    if keyPath == "contentOffset" {
        if let contentOffset = change[NSKeyValueChangeKey.newKey] as? CGPoint {
            let screenWidth = UIScreen.main.bounds.width
            let percent = abs((contentOffset.x - screenWidth) / screenWidth)
            print(percent)
        }
    }
}