如何让一个视图同时支持UISwipeGestureRecognizer和UIPanGestureRecognizer手势?

26
如何设置手势识别器,以使您可以同时使用UISwipeGestureRecognizerUIPanGestureRecognizer?如果您快速触摸并移动(快速轻扫),它将被识别为轻扫手势,但是如果您触摸然后移动(触摸和移动之间有短暂延迟),它将被识别为平移手势?
我已经尝试过各种组合的requireGestureRecognizerToFail,但没有帮助,这样做只能使我的平移手势在向上、向下和向右滑动时正常工作,但任何向左的移动都被轻扫手势检测到。
4个回答

53
你需要设置两个UIGestureRecognizer中的一个委托对象(很可能是self),然后监听并在此方法中返回YES
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
         shouldRecognizeSimultaneouslyWithGestureRecognizer:
                            (UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

gestureRecognizerotherGestureRecognizer的手势识别会阻止另一个手势识别器识别其手势时,将调用此方法。请注意,返回YES可以保证允许同时识别; 而返回NO则不能保证防止同时识别,因为其他手势识别器的委托可能会返回YES


9

默认情况下,当用户尝试滑动时,手势会被解释为平移。这是因为在手势滑动符合被解释为滑动(离散手势)的条件之前,它已经符合了被解释为平移(连续手势)的条件。

您需要通过在想要延迟的手势识别器上调用 requireGestureRecognizerToFail: 方法来指示两个手势识别器之间的关系。

[self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];

谢谢,那帮了大忙。 - Ros
哇,这太棒了。 - Josh

7

使用平移识别器来检测滑动和平移

- (void)setupRecognizer
{
    UIPanGestureRecognizer* panSwipeRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanSwipe:)];
    // Here you can customize for example the minimum and maximum number of fingers required
    panSwipeRecognizer.minimumNumberOfTouches = 2;
    [targetView addGestureRecognizer:panSwipeRecognizer];
}

#define SWIPE_UP_THRESHOLD -1000.0f
#define SWIPE_DOWN_THRESHOLD 1000.0f
#define SWIPE_LEFT_THRESHOLD -1000.0f
#define SWIPE_RIGHT_THRESHOLD 1000.0f

- (void)handlePanSwipe:(UIPanGestureRecognizer*)recognizer
{
    // Get the translation in the view
    CGPoint t = [recognizer translationInView:recognizer.view];
    [recognizer setTranslation:CGPointZero inView:recognizer.view];

    // TODO: Here, you should translate your target view using this translation
    someView.center = CGPointMake(someView.center.x + t.x, someView.center.y + t.y);

    // But also, detect the swipe gesture
    if (recognizer.state == UIGestureRecognizerStateEnded)
    {
        CGPoint vel = [recognizer velocityInView:recognizer.view];

        if (vel.x < SWIPE_LEFT_THRESHOLD)
        {
            // TODO: Detected a swipe to the left
        }
        else if (vel.x > SWIPE_RIGHT_THRESHOLD)
        {
            // TODO: Detected a swipe to the right
        }
        else if (vel.y < SWIPE_UP_THRESHOLD)
        {
            // TODO: Detected a swipe up
        }
        else if (vel.y > SWIPE_DOWN_THRESHOLD)
        {
            // TODO: Detected a swipe down
        }
        else
        {
            // TODO:
            // Here, the user lifted the finger/fingers but didn't swipe.
            // If you need you can implement a snapping behaviour, where based on the location of your         targetView,
            // you focus back on the targetView or on some next view.
            // It's your call
        }
    }
}

3

这里是一个完整的解决方案,用于检测滑动手势的方向(利用2cupsOfTech的swipeThreshold逻辑):

public enum PanSwipeDirection: Int {
    case up, down, left, right, upSwipe, downSwipe, leftSwipe, rightSwipe
    public var isSwipe: Bool { return [.upSwipe, .downSwipe, .leftSwipe, .rightSwipe].contains(self) }
    public var isVertical: Bool { return [.up, .down, .upSwipe, .downSwipe].contains(self) }
    public var isHorizontal: Bool { return !isVertical }
}

public extension UIPanGestureRecognizer {

   var direction: PanSwipeDirection? {
        let SwipeThreshold: CGFloat = 1000
        let velocity = self.velocity(in: view)
        let isVertical = abs(velocity.y) > abs(velocity.x)
        switch (isVertical, velocity.x, velocity.y) {
        case (true, _, let y) where y < 0: return y < -SwipeThreshold ? .upSwipe : .up
        case (true, _, let y) where y > 0: return y > SwipeThreshold ? .downSwipe : .down
        case (false, let x, _) where x > 0: return x > SwipeThreshold ? .rightSwipe : .right
        case (false, let x, _) where x < 0: return x < -SwipeThreshold ? .leftSwipe : .left
        default: return nil
        }
    }

}

使用方法:

@IBAction func handlePanOrSwipe(recognizer: UIPanGestureRecognizer) {

    if let direction = recognizer.direction {
        if direction == .leftSwipe {
            //swiped left
        } else if direction == .up {
            //panned up
        } else if direction.isVertical && direction.isSwipe {
            //swiped vertically
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接