如何让UISwipeGestureRecognizer和UIPanGestureRecognizer在同一视图上工作

时间:2011-02-24 23:24:26

标签: iphone objective-c uigesturerecognizer gesture-recognition

您如何设置手势识别器,以便您可以同时使用 UISwipeGestureRecognizer UIPanGestureRecognizer ?这样,如果您快速触摸并快速移动(快速滑动),它会将手势检测为滑动,但如果您触摸然后移动(触摸和移动之间的短暂延迟),它会将其检测为平底锅?

我已经尝试了 requireGestureRecognizerToFail 的各种排列,这并没有完全帮助,它使得如果离开SwipeGesture然后我的平移手势将向上,向下和向右但任何运动通过滑动手势检测到左侧。

4 个答案:

答案 0 :(得分:51)

您将要将两个UIGestureRecognizer的委托中的一个设置为有意义的对象(可能self)然后侦听,并为此返回YES { {3}}:

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

gestureRecognizerotherGestureRecognizer识别手势会阻止其他手势识别器识别其手势时,会调用此方法。请注意,保证返回YES可以同时识别;另一方面,返回NO并不能保证阻止同时识别,因为其他手势识别器的代表可能会返回YES

答案 1 :(得分:5)

Using a pan recognizer to detect swipping and panning

- (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
        }
    }
}

答案 2 :(得分:4)

默认情况下,当用户尝试滑动时,手势会被解释为平移。这是因为滑动手势在满足被解释为滑动(离散手势)的必要条件之前满足被解释为平移(连续手势)的必要条件。

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

[self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];

答案 3 :(得分:0)

以下是检测摇摄和滑动方向的完整解决方案(使用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 {

    public var direction: PanSwipeDirection? {
        let SwipeThreshold: CGFloat = 1000
        let velocity = self.velocity(in: view)
        let isVertical = fabs(velocity.y) > fabs(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
        }
    }

}