¿Cómo puedo capturar qué dirección se está desplazando usando UIPanGestureRecognizer?


Ok, así que he estado mirando alrededor de casi todas las opciones bajo el sol para capturar gestos multitáctiles, y finalmente he completado el círculo y estoy de vuelta en el UIPanGestureRecognizer.

La funcionalidad que quiero es realmente bastante simple. He configurado un gesto de panorámica de dos dedos, y quiero ser capaz de barajar algunas imágenes dependiendo de cuántos píxeles muevo. Tengo todo lo que funcionó bien, pero quiero ser capaz de capturar si el gesto de pan se INVIERTE.

Es hay una forma construida que no estoy viendo para detectar volver a un gesto? ¿Tendría que almacenar mi punto inicial original, luego rastrear el punto final, luego ver dónde se mueven después de eso y se si es menor que el punto final inicial y luego invertir en consecuencia? Puedo ver que funciona, pero espero que haya una solución más elegante!!

Gracias

EDITAR:

Aquí está el método que el recognizer está configurado para disparar. Es un poco de un hack, pero obras:

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

He llegado al punto en que voy a empezar a tratar de rastrear las diferencias entre los valores...para intentar saber en qué dirección se panorámica

Author: Brandon B., 2011-03-04

3 answers

En UIPanGestureRecognizer puedes usar -velocityInView: para obtener la velocidad de los dedos en el momento en que se reconoció ese gesto.

Si quieres hacer una cosa en una bandeja a la derecha y una cosa en una bandeja a la izquierda, por ejemplo, podrías hacer algo como:

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

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

Si literalmente quieres detectar una reversión, como si quieres comparar una nueva velocidad con una antigua y ver si está justo en la dirección opuesta, cualquiera que sea la dirección que pueda ser, podrías do:

// 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 cosa de multiplicar y sumar puede parecer un poco extraña. En realidad es un producto escalar, pero tenga la seguridad de que será un número positivo si los gestos están en la misma dirección, bajando a 0 si están exactamente en ángulos rectos y luego convertirse en un número negativo si están en la dirección opuesta.

 166
Author: Tommy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-03 22:47:55

Aquí hay un fácil de detectar antes de que comience el reconocedor de gestos:

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 desea un arrastre solo vertical, puede cambiar el x y y.

 9
Author: Sam Soffes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-12 08:55:59

Este código de Serghei Catraniuc funcionó mejor para mí. 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
        }


    }
}

/ / Extensiones

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
        }
    }
}
 6
Author: johndpope,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-13 13:28:38