web-dev-qa-db-fra.com

Comment puis-je capturer la direction qui est panoramique à l'aide d'UIPanGestureRecognizer?

Ok, donc j'ai regardé à peu près toutes les options sous le soleil pour capturer des gestes multi-touch, et j'ai enfin bouclé la boucle et je suis de retour à l'UIPanGestureRecognizer.

La fonctionnalité que je veux est vraiment assez simple. J'ai configuré un mouvement de panoramique à deux doigts et je veux pouvoir parcourir certaines images en fonction du nombre de pixels que je déplace. J'ai tout bien fonctionné, mais je veux pouvoir capturer si le mouvement de panoramique est inversé.

Y a-t-il une manière intégrée que je ne vois tout simplement pas de détecter le retour d'un geste? Dois-je stocker mon point de départ d'origine, puis suivre le point de fin, puis voir où ils se déplacent après cela et voir si c'est moins que le point de fin initial, puis inverser en conséquence? Je peux voir que ça marche, mais j'espère qu'il y a une solution plus élégante !!

Merci

ÉDITER:

Voici la méthode que le module de reconnaissance est défini pour déclencher. C'est un peu un hack, mais ça marche:

-(void) throttle:(UIGestureRecognizer *) recognize{

throttleCounter ++;

if(throttleCounter == 6){
    throttleCounter = 0;
    [self nextPic:nil];
}

UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *) recognize;
UIView *view = recognize.view;
if(panGesture.state == UIGestureRecognizerStateBegan){
    CGPoint translation = [panGesture translationInView:view.superview];
    NSLog(@"X: %f, Y:%f", translation.x, translation.y);
}else if(panGesture.state == UIGestureRecognizerStateEnded){
    CGPoint translation = [panGesture translationInView:view.superview];
            NSLog(@"X: %f, Y:%f", translation.x, translation.y);
}
  }

Je viens d'arriver au point où je vais commencer à essayer de suivre les différences entre les valeurs ... pour essayer de dire de quelle façon ils se déplacent

58
Brandon B.

Sur UIPanGestureRecognizer, vous pouvez utiliser - velocityInView: pour obtenir la vitesse des doigts au moment où le geste a été reconnu.

Si vous vouliez faire une chose à droite et une à gauche, par exemple, vous pourriez faire quelque chose comme:

- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
    CGPoint velocity = [gestureRecognizer velocityInView:yourView];

    if(velocity.x > 0)
    {
        NSLog(@"gesture went right");
    }
    else
    {
        NSLog(@"gesture went left");
    }
}

Si vous voulez littéralement détecter une inversion, comme dans vous voulez comparer une nouvelle vitesse à une ancienne et voir si elle est juste dans la direction opposée - quelle que soit la direction qui peut être - vous pouvez le faire:

// assuming lastGestureVelocity is a class variable...

- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
    CGPoint velocity = [gestureRecognizer velocityInView:yourView];

    if(velocity.x*lastGestureVelocity.x + velocity.y*lastGestureVelocity.y > 0)
    {
        NSLog(@"gesture went in the same direction");
    }
    else
    {
        NSLog(@"gesture went in the opposite direction");
    }

    lastGestureVelocity = velocity;
}

La chose multiplier et ajouter peut sembler un peu étrange. C'est en fait un produit scalaire, mais soyez assuré que ce sera un nombre positif si les gestes sont dans la même direction, descendant à 0 s'ils sont exactement à angle droit et devenant ensuite un nombre négatif s'ils sont dans le sens opposé direction.

173
Tommy

Voici une méthode facile à détecter avant le début de la reconnaissance des gestes:

public override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    guard let panRecognizer = gestureRecognizer as? UIPanGestureRecognizer else {
        return super.gestureRecognizerShouldBegin(gestureRecognizer)
    }

    // Ensure it's a horizontal drag
    let velocity = panRecognizer.velocity(in: self)
    if abs(velocity.y) > abs(velocity.x) {
        return false
    }
    return true
}

Si vous souhaitez un glissement vertical uniquement, vous pouvez basculer entre x et y.

11
Sam Soffes

Ce code de Serghei Catraniuc a mieux fonctionné pour moi. https://github.com/serp1412/LazyTransitions

     func addPanGestureRecognizers() {
       let panGesture = UIPanGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(gesture:)))
        self.view.addGestureRecognizer(panGesture)
     }

     func respondToSwipeGesture(gesture: UIGestureRecognizer){
        if let swipeGesture = gesture as? UIPanGestureRecognizer{

        switch gesture.state {
        case .began:
            print("began")

        case .ended:
             print("ended")
             switch swipeGesture.direction{
             case .rightToLeft:
                print("rightToLeft")
             case .leftToRight:
                print("leftToRight")
             case .topToBottom:
                print("topToBottom")
             case .bottomToTop:
                print("bottomToTop")
             default:
                print("default")
            }

        default: break
        }


    }
}

// Extensions

import Foundation
import UIKit

public enum UIPanGestureRecognizerDirection {
    case undefined
    case bottomToTop
    case topToBottom
    case rightToLeft
    case leftToRight
}
public enum TransitionOrientation {
    case unknown
    case topToBottom
    case bottomToTop
    case leftToRight
    case rightToLeft
}


extension UIPanGestureRecognizer {
    public var direction: UIPanGestureRecognizerDirection {
        let velocity = self.velocity(in: view)
        let isVertical = fabs(velocity.y) > fabs(velocity.x)

        var direction: UIPanGestureRecognizerDirection

        if isVertical {
            direction = velocity.y > 0 ? .topToBottom : .bottomToTop
        } else {
            direction = velocity.x > 0 ? .leftToRight : .rightToLeft
        }

        return direction
    }

    public func isQuickSwipe(for orientation: TransitionOrientation) -> Bool {
        let velocity = self.velocity(in: view)
        return isQuickSwipeForVelocity(velocity, for: orientation)
    }

    private func isQuickSwipeForVelocity(_ velocity: CGPoint, for orientation: TransitionOrientation) -> Bool {
        switch orientation {
        case .unknown : return false
        case .topToBottom : return velocity.y > 1000
        case .bottomToTop : return velocity.y < -1000
        case .leftToRight : return velocity.x > 1000
        case .rightToLeft : return velocity.x < -1000
        }
    }
}

extension UIPanGestureRecognizer {
    typealias GestureHandlingTuple = (gesture: UIPanGestureRecognizer? , handle: (UIPanGestureRecognizer) -> ())
    fileprivate static var handlers = [GestureHandlingTuple]()

    public convenience init(gestureHandle: @escaping (UIPanGestureRecognizer) -> ()) {
        self.init()
        UIPanGestureRecognizer.cleanup()
        set(gestureHandle: gestureHandle)
    }

    public func set(gestureHandle: @escaping (UIPanGestureRecognizer) -> ()) {
        weak var weakSelf = self
        let Tuple = (weakSelf, gestureHandle)
        UIPanGestureRecognizer.handlers.append(Tuple)
        addTarget(self, action: #selector(handleGesture))
    }

    fileprivate static func cleanup() {
        handlers = handlers.filter { $0.0?.view != nil }
    }

    @objc private func handleGesture(_ gesture: UIPanGestureRecognizer) {
        let handleTuples = UIPanGestureRecognizer.handlers.filter{ $0.gesture === self }
        handleTuples.forEach { $0.handle(gesture)}
    }
}

extension UIPanGestureRecognizerDirection {
    public var orientation: TransitionOrientation {
        switch self {
        case .rightToLeft: return .rightToLeft
        case .leftToRight: return .leftToRight
        case .bottomToTop: return .bottomToTop
        case .topToBottom: return .topToBottom
        default: return .unknown
        }
    }
}

extension UIPanGestureRecognizerDirection {
    public var isHorizontal: Bool {
        switch self {
        case .rightToLeft, .leftToRight:
            return true
        default:
            return false
        }
    }
}
7
johndpope