webentwicklung-frage-antwort-db.com.de

Wie kann ich mit UIPanGestureRecognizer erfassen, in welche Richtung geschwenkt wird?

Ok, ich habe mich nach so gut wie allen Optionen unter der Sonne umgesehen, um Multitouch-Gesten zu erfassen, und bin endlich wieder bei UIPanGestureRecognizer angelangt.

Die Funktionalität, die ich möchte, ist wirklich recht einfach. Ich habe eine Zwei-Finger-Schwenk-Geste eingerichtet und möchte in der Lage sein, einige Bilder zu durchlaufen, je nachdem, wie viele Pixel ich bewege. Ich habe alles in Ordnung, aber ich möchte in der Lage sein, zu erfassen, ob die Pan-Geste umgekehrt ist.

Gibt es eine eingebaute Art und Weise, die ich gerade nicht sehe, um zu ermitteln, auf eine Geste zurückzugehen? Müsste ich meinen ursprünglichen Startpunkt speichern, dann den Endpunkt verfolgen, dann sehen, wo sie sich danach bewegen und se, wenn es weniger als der ursprüngliche Endpunkt ist, und dann dementsprechend umkehren? Ich kann das sehen, aber ich hoffe, es gibt eine elegantere Lösung !!

Vielen Dank

BEARBEITEN:

Hier ist die Methode, mit der der Erkenner ausgelöst wird. Es ist ein bisschen ein Hack, aber es funktioniert:

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

Ich bin gerade an dem Punkt angelangt, an dem ich versuchen werde, die Unterschiede zwischen den Werten zu verfolgen ... um zu versuchen, festzustellen, in welche Richtung sie schwenken

58
Brandon B.

In UIPanGestureRecognizer können Sie - velocityInView: verwenden, um die Geschwindigkeit der Finger zum Zeitpunkt der Erkennung der Geste abzurufen.

Wenn Sie zum Beispiel eine Sache auf einer Pfanne rechts und eine Sache auf einer Pfanne links tun möchten, können Sie Folgendes tun:

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

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

Wenn Sie buchstäblich eine Umkehrung erkennen möchten, wie Sie eine neue Geschwindigkeit mit einer alten Geschwindigkeit vergleichen möchten, und prüfen möchten, ob sie genau in die entgegengesetzte Richtung zeigt - in welcher Richtung auch immer -, können Sie Folgendes tun:

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

Das Multiplizieren und Addieren sieht vielleicht etwas seltsam aus. Eigentlich ist es ein Skalarprodukt, aber Sie können sicher sein, dass es eine positive Zahl ist, wenn die Gesten in die gleiche Richtung zeigen. Wenn sie genau im rechten Winkel stehen, wird es zu einer negativen Zahl, wenn sie sich im Gegenteil befinden Richtung.

173
Tommy

Dies ist leicht zu erkennen, bevor die Gestenerkennung beginnt:

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
}

Wenn Sie nur vertikal ziehen möchten, können Sie zwischen x und y wechseln.

11
Sam Soffes

Dieser Code von Serghei Catraniuc hat für mich besser funktioniert. 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
        }


    }
}

// Erweiterungen

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