订购手势识别器
Ordering gesture recognisers
我想知道是否可以就某个问题得到一些澄清,因为我发现 Apple 的文档非常不清楚。我已将边缘平移手势添加到 UIScrollView(或更准确地说是 UIPageViewController 的滚动视图),我发现滚动视图的 swipe/pan 手势与我添加的边缘平移手势冲突。
编辑:按照下面的要求,这是我用来在滚动视图上实现手势的代码和我使用的委托函数。
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 Recognisers, Preferring One Gesture Over Another),但他们的文档没有帮助。在这两份文件的第一份中,有一节内容如下:
To prevent the unintended side effects of the default recognition behavior, you can tell UIKit to recognize gestures in a specific order using a delegate object. UIKit uses the methods of your delegate object to determine whether a gesture recognizer must come before or after other gesture recognizers.
这正是我想要实现的,因为我希望边缘滑动优先于滚动视图的其他手势。但是,该部分继续讨论通过实现我已经实现的 UIGestureRecognizerDelegate 方法 shouldRequireFailureOf 来实现这一点,但是由于滚动视图的平移手势实际上直到手指抬起后才会失败,所以这样做没有什么比边缘手势更喜欢的了。
我还实现了 shouldRecognizeSimultaneouslyWith 方法,它确实解决了冲突,但它也会导致滚动视图在边缘平移期间滚动。
我希望能够按照摘录中所说的那样做,并以特定顺序识别我的手势。非常感谢任何有助于实现这一目标的帮助。
谢谢!
这有点远,但在我看来,您应该将 leftEdge 识别器设置为延迟触摸事件,并使 table 识别器要求 leftEdge 在接管之前失败。
leftEdge.delaysTouchesBegan = true
tableView.panGestureRecognizer.require(toFail: leftEdge)
对于任何试图在未来实现这一非常小众的东西的人,我找到了解决方法。
我像这样实现了 UIGestureRecognizerDelegate 方法 shouldRecognizeSimultaneouslyWith:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
因为我只在我的边缘平移手势上实现了委托(如上所示),所以它只在边缘平移被激活时被调用。这停止了我的边缘平移和滚动视图的平移之间的冲突,但引入了 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
。这意味着即使弹出手势被取消,视图之间的分页仍然有效。
这不是一个很好的解决方案,但它确实具有使边缘手势优先于平移手势的预期效果,只是以一种非常不优雅的方式。如果出现更好的答案,我将编辑此 post。
我想知道是否可以就某个问题得到一些澄清,因为我发现 Apple 的文档非常不清楚。我已将边缘平移手势添加到 UIScrollView(或更准确地说是 UIPageViewController 的滚动视图),我发现滚动视图的 swipe/pan 手势与我添加的边缘平移手势冲突。
编辑:按照下面的要求,这是我用来在滚动视图上实现手势的代码和我使用的委托函数。
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 Recognisers, Preferring One Gesture Over Another),但他们的文档没有帮助。在这两份文件的第一份中,有一节内容如下:
To prevent the unintended side effects of the default recognition behavior, you can tell UIKit to recognize gestures in a specific order using a delegate object. UIKit uses the methods of your delegate object to determine whether a gesture recognizer must come before or after other gesture recognizers.
这正是我想要实现的,因为我希望边缘滑动优先于滚动视图的其他手势。但是,该部分继续讨论通过实现我已经实现的 UIGestureRecognizerDelegate 方法 shouldRequireFailureOf 来实现这一点,但是由于滚动视图的平移手势实际上直到手指抬起后才会失败,所以这样做没有什么比边缘手势更喜欢的了。
我还实现了 shouldRecognizeSimultaneouslyWith 方法,它确实解决了冲突,但它也会导致滚动视图在边缘平移期间滚动。
我希望能够按照摘录中所说的那样做,并以特定顺序识别我的手势。非常感谢任何有助于实现这一目标的帮助。
谢谢!
这有点远,但在我看来,您应该将 leftEdge 识别器设置为延迟触摸事件,并使 table 识别器要求 leftEdge 在接管之前失败。
leftEdge.delaysTouchesBegan = true
tableView.panGestureRecognizer.require(toFail: leftEdge)
对于任何试图在未来实现这一非常小众的东西的人,我找到了解决方法。
我像这样实现了 UIGestureRecognizerDelegate 方法 shouldRecognizeSimultaneouslyWith:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
因为我只在我的边缘平移手势上实现了委托(如上所示),所以它只在边缘平移被激活时被调用。这停止了我的边缘平移和滚动视图的平移之间的冲突,但引入了 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
。这意味着即使弹出手势被取消,视图之间的分页仍然有效。
这不是一个很好的解决方案,但它确实具有使边缘手势优先于平移手势的预期效果,只是以一种非常不优雅的方式。如果出现更好的答案,我将编辑此 post。