UIPageViewController 在 UIScrollView 上有条件地滑动

UIPageViewController Swipe Conditional On UIScrollView

我见过类似的问题here,但没有有效的解决方案。

我有一个 UIScrollView 嵌入在 UIPageViewController 中。我想让用户能够正常滚动 UIScrollView。然后,如果到达 UIScrollView 的一端(例如一直向左),则向左滑动(向右滑动,但你明白我的意思)将触发 UIPageViewController 向左移动到另一页。

默认行为有点粗略。手势识别器似乎在竞争,在某些情况下 UIScrollView 确实滚动,而在其他情况下,PageView 只是转移到下一页。我希望能够将此行为与 UIScrollView 或其他内容的内容偏移联系起来。

我将尝试在各种手势识别器上使用 requireFail 方法进行一些实验,但似乎 PageView 的所有手势识别器属性都被取消了,因为我正在使用滚动过渡类型。那么...走层次结构?

无论如何,如果有人知道解决这个问题的简单方法,我将不胜感激。

我最终解决这个问题的方法是使用 UIPageViewController 的替代品:EMPageViewController。因为我可以直接访问 UIScrollView,所以我能够对其进行子类化。

解决方案基本上是子类化并向 UIScrollView 添加切换标志(一个用于 EMPageViewController 和一个在其中)以控制它们何时应该处于活动状态,基于基于各种因素(例如其中一个滚动视图的内容偏移量)。然后我能够在 UIScrollView 子类中以不同的方式覆盖 gestureRecognizerShouldBegin:gestureRecognizer,检查切换标志和平移手势识别器的速度。

像这样(断章取义的代码):

import UIKit

class CustomScrollView: UIScrollView {

    // these toggles get set by some senior ViewController
    var lockDown = false
    var lockUp = false

    override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
        print("= gesture starting")
        if let panner = gestureRecognizer as? UIPanGestureRecognizer {
            if panner.velocityInView(self).y < 0.0 {
                print("== pulling down, lockDown: \(lockDown)")
                if lockDown {
                    print("=== cancelling paging scroll")
                    return false
                }
            }
            if panner.velocityInView(self).y > 0.0 {
                print("== pulling up, lockUp: \(lockUp)")
                if lockUp {
                    print("=== cancelling paging scroll")
                    return false
                }
            }
        }

        return super.gestureRecognizerShouldBegin(gestureRecognizer)
    }

}

无论如何,我最终确实顺利地完成了所有工作。每个人的用例可能略有不同,但底线是您需要子类化 UIScrollView,因此 UIPageViewController 不是一个选项。