How to have a UISwipeGestureRecognizer AND UIPanGestureRecognizer work on the same view

后端 未结 4 1102
春和景丽
春和景丽 2020-12-04 19:58

How would you setup the gesture recognizers so that you could have a UISwipeGestureRecognizer and a UIPanGestureRecognizer work at the same

相关标签:
4条回答
  • 2020-12-04 20:23

    Here is a full solution for detecting pan and swipe directions (utilizing 2cupsOfTech's swipeThreshold logic):

    public enum PanSwipeDirection: Int {
        case up, down, left, right, upSwipe, downSwipe, leftSwipe, rightSwipe
        public var isSwipe: Bool { return [.upSwipe, .downSwipe, .leftSwipe, .rightSwipe].contains(self) }
        public var isVertical: Bool { return [.up, .down, .upSwipe, .downSwipe].contains(self) }
        public var isHorizontal: Bool { return !isVertical }
    }
    
    public extension UIPanGestureRecognizer {
    
       var direction: PanSwipeDirection? {
            let SwipeThreshold: CGFloat = 1000
            let velocity = self.velocity(in: view)
            let isVertical = abs(velocity.y) > abs(velocity.x)
            switch (isVertical, velocity.x, velocity.y) {
            case (true, _, let y) where y < 0: return y < -SwipeThreshold ? .upSwipe : .up
            case (true, _, let y) where y > 0: return y > SwipeThreshold ? .downSwipe : .down
            case (false, let x, _) where x > 0: return x > SwipeThreshold ? .rightSwipe : .right
            case (false, let x, _) where x < 0: return x < -SwipeThreshold ? .leftSwipe : .left
            default: return nil
            }
        }
    
    }
    

    Usage:

    @IBAction func handlePanOrSwipe(recognizer: UIPanGestureRecognizer) {
    
        if let direction = recognizer.direction {
            if direction == .leftSwipe {
                //swiped left
            } else if direction == .up {
                //panned up
            } else if direction.isVertical && direction.isSwipe {
                //swiped vertically
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-04 20:24

    Using a pan recognizer to detect swipping and panning:

    - (void)setupRecognizer
    {
        UIPanGestureRecognizer* panSwipeRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanSwipe:)];
        // Here you can customize for example the minimum and maximum number of fingers required
        panSwipeRecognizer.minimumNumberOfTouches = 2;
        [targetView addGestureRecognizer:panSwipeRecognizer];
    }
    
    #define SWIPE_UP_THRESHOLD -1000.0f
    #define SWIPE_DOWN_THRESHOLD 1000.0f
    #define SWIPE_LEFT_THRESHOLD -1000.0f
    #define SWIPE_RIGHT_THRESHOLD 1000.0f
    
    - (void)handlePanSwipe:(UIPanGestureRecognizer*)recognizer
    {
        // Get the translation in the view
        CGPoint t = [recognizer translationInView:recognizer.view];
        [recognizer setTranslation:CGPointZero inView:recognizer.view];
    
        // TODO: Here, you should translate your target view using this translation
        someView.center = CGPointMake(someView.center.x + t.x, someView.center.y + t.y);
    
        // But also, detect the swipe gesture
        if (recognizer.state == UIGestureRecognizerStateEnded)
        {
            CGPoint vel = [recognizer velocityInView:recognizer.view];
    
            if (vel.x < SWIPE_LEFT_THRESHOLD)
            {
                // TODO: Detected a swipe to the left
            }
            else if (vel.x > SWIPE_RIGHT_THRESHOLD)
            {
                // TODO: Detected a swipe to the right
            }
            else if (vel.y < SWIPE_UP_THRESHOLD)
            {
                // TODO: Detected a swipe up
            }
            else if (vel.y > SWIPE_DOWN_THRESHOLD)
            {
                // TODO: Detected a swipe down
            }
            else
            {
                // TODO:
                // Here, the user lifted the finger/fingers but didn't swipe.
                // If you need you can implement a snapping behaviour, where based on the location of your         targetView,
                // you focus back on the targetView or on some next view.
                // It's your call
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-04 20:26

    You're going to want to set one of the two UIGestureRecognizer's delegates to an object that makes sense (likely self) then listen, and return YES for this method:

    - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
             shouldRecognizeSimultaneouslyWithGestureRecognizer:
                                (UIGestureRecognizer *)otherGestureRecognizer {
        return YES;
    }
    

    This method is called when recognition of a gesture by either gestureRecognizer or otherGestureRecognizer would block the other gesture recognizer from recognizing its gesture. Note that returning YES is guaranteed to allow simultaneous recognition; returning NO, on the other hand, is not guaranteed to prevent simultaneous recognition because the other gesture recognizer's delegate may return YES.

    0 讨论(0)
  • 2020-12-04 20:40

    By default, when the user attempts to swipe, the gesture is interpreted as a pan. This is because a swiping gesture meets the necessary conditions to be interpreted as a pan (a continuous gesture) before it meets the necessary conditions to be interpreted as a swipe (a discrete gesture).

    You need to indicate a relationship between two gesture recognizers by calling the requireGestureRecognizerToFail: method on the gesture recognizer that you want to delay

    [self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];
    
    0 讨论(0)
提交回复
热议问题