63 votes

Comment puis-je capturer la direction dans laquelle le balayage est effectué en utilisant UIPanGestureRecognizer ?

D'accord, donc j'ai regardé à peu près toutes les options possibles pour capturer des gestes multi-touch, et je suis finalement revenu à l'UIPanGestureRecognizer.

La fonctionnalité que je veux est vraiment assez simple. J'ai configuré un geste de panoramique à deux doigts, et je veux pouvoir faire défiler quelques images en fonction du nombre de pixels que je déplace. J'ai tout cela bien fonctionné, mais je veux être capable de capturer si le geste de panoramique est INVERSÉ.

Y a-t-il un moyen intégré que je ne vois tout simplement pas pour détecter un retour sur un geste? Dois-je stocker mon point de départ d'origine, puis suivre le point final, puis voir où ils se déplacent après cela et voir s'ils sont inférieurs au point final initial et ensuite inverser en conséquence? Je peux voir que cela fonctionnerait, mais j'espère qu'il y a une solution plus élégante!!

Merci

ÉDITER:

Voici la méthode à laquelle le reconnaissseur est configuré pour déclencher. C'est un peu une astuce, 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 dans quelle direction ils font du panoramique

0 votes

Pouvez-vous poster l'implémentation de la méthode que votre détecteur de geste de panoramique déclenche?

180voto

Tommy Points 56749

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

Si vous voulez faire une chose sur un balayage vers la droite et une chose sur un balayage vers la gauche, par exemple, vous pourriez faire quelque chose comme :

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

    if(velocity.x > 0)
    {
        NSLog(@"le geste est allé vers la droite");
    }
    else
    {
        NSLog(@"le geste est allé vers la gauche");
    }
}

Si vous voulez littéralement détecter une inversion, c'est-à-dire comparer une nouvelle vitesse à une ancienne et voir si elle est juste dans la direction opposée - quelle que soit la direction - vous pourriez faire :

// en supposant que lastGestureVelocity est une variable de classe...

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

    if(velocity.x*lastGestureVelocity.x + velocity.y*lastGestureVelocity.y > 0)
    {
        NSLog(@"le geste est allé dans la même direction");
    }
    else
    {
        NSLog(@"le geste est allé dans la direction opposée");
    }

    lastGestureVelocity = velocity;
}

La multiplication et l'addition peuvent sembler un peu étranges. En fait, c'est un produit scalaire, mais soyez assuré que ce sera un nombre positif si les gestes vont dans la même direction, en descendant jusqu'à 0 s'ils sont exactement à angles droits, puis devenant un nombre négatif s'ils vont dans la direction opposée.

0 votes

Wow! Way above and beyond the call of duty. That answer is exactly what I needed!!! Thanks Tommmy!

0 votes

C'est exactement ce que je cherchais! Merci! :)

17voto

Sam Soffes Points 8034

Voici un moyen facile de détecter avant que le reconnaissant de geste commence :

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

    // Assurez-vous que c'est un glissement horizontal
    let velocity = panRecognizer.velocity(in: self)
    if abs(velocity.y) > abs(velocity.x) {
        return false
    }
    return true
}

Si vous voulez un glissement uniquement vertical, vous pouvez échanger le x et le y.

11voto

johndpope Points 1485

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X