Подтвердить что ты не робот

Как работать с UISwipeGestureRecognizer и UIPanGestureRecognizer на одном и том же представлении

Как бы вы настроили распознаватели жестов, чтобы вы могли одновременно работать с UISwipeGestureRecognizer и UIPanGestureRecognizer? Таким образом, если вы прикоснетесь и быстро двигаетесь (быстро проведите по экрану), он обнаруживает жест как салфетки, но если вы коснетесь, тогда переместите (короткая задержка между касанием и движением), он обнаруживает его как панораму?

Я пробовал различные перестановки requireGestureRecognizerToFail, и это не помогло точно, это сделало так, чтобы, если SwipeGesture остался, мой жест пота будет работать вверх, вниз и вправо, но любое движение левый был обнаружен жестом салфетки.

4b9b3361

Ответ 1

Вам захочется установить один из двух делегатов UIGestureRecognizer объекту, который имеет смысл (скорее всего, self), а затем прослушать и вернуть YES для этого метод:

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

Этот метод вызывается, когда распознавание жеста с помощью gestureRecognizer или otherGestureRecognizer блокирует другой распознаватель жестов от распознавания его жеста. Обратите внимание, что возвращение YES гарантировано для одновременного распознавания; с другой стороны, возврат NO не гарантирует одновременное распознавание, потому что другой делегат распознавателя жеста может возвращать YES.

Ответ 2

Использование распознавателя панорамирования для обнаружения перелистывания и панорамирования:

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

Ответ 3

По умолчанию, когда пользователь пытается провести салфетки, этот жест интерпретируется как панорама. Это происходит из-за того, что махающий жест соответствует необходимым условиям, которые следует интерпретировать как кастрюлю (непрерывный жест), прежде чем он удовлетворит необходимые условия, которые будут интерпретироваться как салфетки (дискретный жест).

Вам нужно указать связь между двумя распознавателями жестов, вызвав метод requireGestureRecognizerToFail: на распознавателе жестов, который вы хотите отложить

[self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];

Ответ 4

Вот полное решение для определения направления панорамирования и пролистывания (с использованием логики 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
        }
    }

}