How can I capture which direction is being panned using UIPanGestureRecognizer?

后端 未结 3 1765
暖寄归人
暖寄归人 2021-01-29 20:43

Ok so I have been looking around at just about every option under the sun for capturing multi-touch gestures, and I have finally come full circle and am back at the UIPanGesture

相关标签:
3条回答
  • 2021-01-29 21:05

    On UIPanGestureRecognizer you can use -velocityInView: to get the velocity of the fingers at the time that gesture was recognised.

    If you wanted to do one thing on a pan right and one thing on a pan left, for example, you could do something like:

    - (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
    {
        CGPoint velocity = [gestureRecognizer velocityInView:yourView];
    
        if(velocity.x > 0)
        {
            NSLog(@"gesture went right");
        }
        else
        {
            NSLog(@"gesture went left");
        }
    }
    

    If you literally want to detect a reversal, as in you want to compare a new velocity to an old one and see if it is just in the opposite direction — whichever direction that may be — you could 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;
    }
    

    The multiply and add thing may look a little odd. It's actually a dot product, but rest assured it'll be a positive number if the gestures are in the same direction, going down to 0 if they're exactly at right angles and then becoming a negative number if they're in the opposite direction.

    0 讨论(0)
  • 2021-01-29 21:05

    This code from Serghei Catraniuc worked out better for me. 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
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-29 21:14

    Here's an easy to detect before the gesture recognizer begins:

    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
    }
    

    If you want a vertical only drag, you can switch the x and y.

    0 讨论(0)
提交回复
热议问题