【问题标题】:How to have a UISwipeGestureRecognizer AND UIPanGestureRecognizer work on the same view如何让 UISwipeGestureRecognizer 和 UIPanGestureRecognizer 在同一个视图上工作
【发布时间】:2011-02-24 23:24:26
【问题描述】:

您将如何设置手势识别器以使 UISwipeGestureRecognizerUIPanGestureRecognizer 同时工作?这样,如果您触摸并快速移动(快速滑动),它会将手势检测为滑动,但如果您触摸然后移动(触摸和移动之间的短暂延迟),它会将其检测为平移?

我已经尝试了 requireGestureRecognizerToFail 的各种排列,但并没有完全帮助,它使得如果 SwipeGesture 离开,那么我的平移手势将向上、向下和向右工作,但任何移动滑动手势检测到向左。

【问题讨论】:

    标签: iphone objective-c uigesturerecognizer gesture-recognition


    【解决方案1】:

    您将希望将两个UIGestureRecognizer 的代表之一设置为有意义的对象(可能是self),然后收听,并为此method 返回YES

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

    当通过gestureRecognizerotherGestureRecognizer 识别手势会阻止其他手势识别器识别其手势时,将调用此方法。注意返回YES保证允许同时识别;另一方面,返回 NO 不能保证防止同时识别,因为其他手势识别器的委托可能会返回 YES

    【讨论】:

      【解决方案2】:

      默认情况下,当用户尝试滑动时,手势被解释为平移。这是因为滑动手势在满足被解释为滑动(离散手势)的必要条件之前,先满足被解释为平移(连续手势)的必要条件。

      您需要通过在要延迟的手势识别器上调用 requireGestureRecognizerToFail: 方法来指示两个手势识别器之间的关系

      [self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];
      

      【讨论】:

      • 感谢您的帮助
      • 哇这太棒了
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        这是检测平移和滑动方向的完整解决方案(利用 2cupsOfTech 的 swipeThreshold 逻辑):

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

        用法:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-27
          • 1970-01-01
          • 2013-06-11
          相关资源
          最近更新 更多