订购手势识别器

时间:2018-01-17 03:42:28

标签: swift swift3

我想知道我是否可以对某个问题做一些澄清,因为我发现Apple的文档非常不清楚。我已经向UIScrollView添加了一个边缘平移手势(或者更准确地说是UIPageViewController的滚动视图),我发现滚动视图的滑动/平移手势与我添加的边缘平移手势发生冲突。

编辑:根据下面的要求,这里是我用来在滚动视图上实现手势的代码以及我使用过的委托函数。

PageViewController VDL:

override func viewDidLoad(){
    super.viewDidLoad()

    self.dataSource = self

    for eachSubView in self.view.subviews {

        if String(describing: type(of: eachSubView)) ==  "_UIQueuingScrollView" {

            let leftEdge = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(handleSwipeFromLeft(_:)))
            leftEdge.edges = .left
            leftEdge.delegate = self
            eachSubView.addGestureRecognizer(leftEdge)

        }

    }

}

处理从左侧滑动功能:

func handleSwipeFromLeft(_ gesture: UIScreenEdgePanGestureRecognizer) {

    let percent = gesture.translation(in: gesture.view!).x / gesture.view!.bounds.size.width

    if gesture.state == .began {

        interactionController = UIPercentDrivenInteractiveTransition()
        if self.navigationController!.viewControllers.count > 1 {
            self.navigationController?.popViewController(animated: true)
        } else {
            dismiss(animated: true)
        }

    } else if gesture.state == .changed {
        interactionController?.update(percent / 4.8)
    } else if gesture.state == .ended {

        if percent > 0.2 && gesture.state != .cancelled {
            interactionController?.finish()
        } else {
            interactionController?.cancel()
        }

        interactionController = nil
    }
}

GestureRecogniserDelegate:

extension ArticleViewPageController: UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        if String(describing: type(of: gestureRecognizer)) == "UIScreenEdgePanGestureRecognizer" {
            return false
        } else {
            return true
        }

    }

}

我一直在阅读Apple关于此问题的文档(Coordinating Multiple Gesture RecognisersPreferring One Gesture Over Another),但他们的文档没有帮助。在这两份文件的第一篇中有一节内容如下:

  

为了防止默认识别行为的意外副作用,您可以告诉UIKit使用委托对象以特定顺序识别手势。 UIKit使用委托对象的方法来确定手势识别器是否必须在其他手势识别器之前或之后出现。

这正是我想要实现的目标,因为我希望优先选择边缘滑动滚动视图的其他手势。然而,该部分继续讨论通过实现我已实现的UIGestureRecognizerDelegate方法 shouldRequireFailureOf 来实现这一点,但由于scrollview的平移手势直到手指被抬起后才真正失败,没有优先选择边缘手势。

我还实现了 shouldRecognizeSimultaneouslyWith 方法,该方法确实解决了冲突,但它也导致滚动视图在边缘平移期间滚动。

我希望能够按照摘录说出来并按特定顺序识别我的手势。任何帮助实现这一点将非常感激。

谢谢!

2 个答案:

答案 0 :(得分:1)

这有点远,但对我而言,你应该设置你的leftEdge识别器来延迟触摸事件并使表识别器要求leftEdge在它可以接管之前失败。

leftEdge.delaysTouchesBegan = true
tableView.panGestureRecognizer.require(toFail: leftEdge)

答案 1 :(得分:1)

对于任何想要在未来实现这个非常小众的人,我找到了一个解决方案。

我实现了UIGestureRecognizerDelegate方法 shouldRecognizeSimultaneouslyWith ,如下所示:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {

    return true

} 

因为我只在我的边缘平移手势上实现了委托(如上所示),所以只有在激活边缘平移时才会调用它。这停止了​​我的边缘平移和scrollview的平移之间的冲突,但引入了PageViewController分页的问题,而我的边缘平移导致导航堆栈中的弹回。为了抵消这一点,我将以下代码添加到我的边缘手势功能(再次,如上所述),当手势状态为.begun时调用:

for eachSubView in self.view.subviews {

    if String(describing: type(of: eachSubView)) ==  "_UIQueuingScrollView", let queueScrollView = eachSubView as? UIScrollView {
        queueScrollView.isScrollEnabled = false
    }

}

最后,我将相同的块添加到我的PageViewController中的viewDidAppear函数,除了我设置queueScrollView.isScrollEnabled = true。这意味着即使取消了弹出手势,视图之间的分页仍然有效。

这不是一个很棒的解决方案,但它确实具有将边缘手势优先于平移手势的预期效果,只是以非常不优雅的方式。如果有更好的答案,我会编辑这篇文章。