拦截 UIScrollView 上的平移手势会中断滚动

问题描述 投票:0回答:4

我有一个垂直滚动

UIScrollView
。我还想在其上处理水平平移,同时允许默认的垂直滚动行为。我在滚动视图上放置了一个透明的
UIView
,并向其添加了一个平移手势识别器。这样我就可以很好地得到平底锅,但是滚动视图不会收到任何手势。

我已经实现了以下

UIPanGestureRecognizerDelegate
方法,希望将我的手势识别器限制为水平平移,但这没有帮助:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer {
    // Only accept horizontal pans here.
    // Leave the vertical pans for scrolling the content.
    CGPoint translation = [gestureRecognizer translationInView:self.view];
    BOOL isHorizontalPan = (fabsf(translation.x) > fabsf(translation.y));
    return  isHorizontalPan;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return (otherGestureRecognizer == _scrollView.panGestureRecognizer);
}
ios ios5 uiscrollview uigesturerecognizer uipangesturerecognizer
4个回答
53
投票

好的,我明白了。我需要做两件事来完成这项工作:

1) 将我自己的平移识别器附加到滚动视图本身,而不是它上面的另一个视图。

2) 这个

UIGestureRecognizerDelegate
方法可以防止在同时调用默认滚动视图和我自己的滚动视图时发生的愚蠢行为。

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

18
投票

我有同样的问题要解决,我这样做了:

1) 将我自己的平移识别器附加到滚动视图。

2) 返回 YES: – gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:

这将使两种手势都起作用。所以这意味着在垂直滚动时,你的 panGesture 委托和 scrollView 委托都将被触发。如果是水平滚动,它只会调用你的 panGesture 委托。

3) 在我的 panGesture 委托中,检测它是否是水平滚动,如果不是,则忽略。


9
投票

快速回答:

let scrollViewPanGesture = UIPanGestureRecognizer(target: self, action: #selector(onPan(_:)))
scrollViewPanGesture.delegate = self
scrollView.addGestureRecognizer(scrollViewPanGesture)

extension ViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

0
投票

对于非常肛门的程序员:

你不会随心所欲地返回 true。您应该检查“其他”手势是否确实是有问题的滚动视图。

这很复杂,因为滚动视图附加了许多手势识别器。

您可以执行此操作以查看所有内容,以及在阅读本文时(当前)UIKit 中有多少

print("count \(primaryScroll.gestureRecognizers?.count)")
print("count \(primaryScroll.gestureRecognizers)") 

所以,完整的解决方案是:

import UIKit
class Examp: UIViewController, UIGestureRecognizerDelegate {
    
    var primaryScroll: UIScrollView ... your scroll view in question

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let p = UIPanGestureRecognizer(target: self, action: #selector(panned))
        p.delegate = self
        primaryScroll.addGestureRecognizer(p)
    }
    
    func gestureRecognizer(
     _ g: UIGestureRecognizer,
     shouldRecognizeSimultaneouslyWith other: UIGestureRecognizer) -> Bool {

        guard
         let gg = primaryScroll.gestureRecognizers,
         gg.contains(other) else { return false }

        return true
    }

    @objc func panned(p: UIPanGestureRecognizer) {
        let v = p.velocity(in: view).x
        if p.state == .ended && abs(v) > 300 { print("swiped") }
        // etc ...
    }

就是这样。

如果您不检查

other
手势实际上是有问题的滚动视图,您将遇到一个非常难以调试的问题。

© www.soinside.com 2019 - 2024. All rights reserved.