简体   繁体   English

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

[英]How to have a UISwipeGestureRecognizer AND UIPanGestureRecognizer work on the same view

How would you setup the gesture recognizers so that you could have a UISwipeGestureRecognizer and a UIPanGestureRecognizer work at the same time? 您将如何设置手势识别器,以便您可以同时使用UISwipeGestureRecognizerUIPanGestureRecognizer Such that if you touch and move quickly (quick swipe) it detects the gesture as a swipe but if you touch then move (short delay between touch & move) it detects it as a pan? 这样,如果您快速触摸并快速移动(快速滑动),它会将手势检测为滑动,但如果您触摸然后移动(触摸和移动之间的短暂延迟),它会将其检测为平移?

I've tried various permutations of requireGestureRecognizerToFail and that didn't help exactly, it made it so that if the SwipeGesture was left then my pan gesture would work up, down and right but any movement left was detected by the swipe gesture. 我已经尝试了requireGestureRecognizerToFail的各种排列,并且没有完全帮助,它使得如果离开SwipeGesture然后我的平移手势将向上,向下和向右工作但是滑动手势检测到任何左移动。

You're going to want to set one of the two UIGestureRecognizer 's delegates to an object that makes sense (likely self ) then listen, and return YES for this method : 您将要将两个UIGestureRecognizer的委托中的一个设置为有意义的对象(可能是self )然后侦听,并为此方法返回YES

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

This method is called when recognition of a gesture by either gestureRecognizer or otherGestureRecognizer would block the other gesture recognizer from recognizing its gesture. 当通过gestureRecognizerotherGestureRecognizer识别手势将阻止其他手势识别器识别其手势时,调用此方法。 Note that returning YES is guaranteed to allow simultaneous recognition; 请注意,保证返回YES可以同时识别; returning NO , on the other hand, is not guaranteed to prevent simultaneous recognition because the other gesture recognizer's delegate may return YES . 另一方面,返回NO不能保证防止同时识别,因为另一个手势识别器的代表可能返回YES

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

By default, when the user attempts to swipe, the gesture is interpreted as a pan. 默认情况下,当用户尝试滑动时,手势将被解释为平移。 This is because a swiping gesture meets the necessary conditions to be interpreted as a pan (a continuous gesture) before it meets the necessary conditions to be interpreted as a swipe (a discrete gesture). 这是因为滑动手势满足必要条件以在其满足被解释为滑动(离散手势)的必要条件之前被解释为平移(连续手势)。

You need to indicate a relationship between two gesture recognizers by calling the requireGestureRecognizerToFail: method on the gesture recognizer that you want to delay 您需要通过调用要延迟的手势识别器上的requireGestureRecognizerToFail:方法来指示两个手势识别器之间的关系

[self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];

Here is a full solution for detecting pan and swipe directions (utilizing 2cupsOfTech's swipeThreshold logic): 这是一个检测平移和滑动方向的完整解决方案(利用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
        }
    }

}

Usage: 用法:

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM