Combining a UILongPressGestureRecognizer with a UIPanGestureRecognizer

前端 未结 6 404
醉梦人生
醉梦人生 2020-11-30 08:57

I d\'like to combine a UILongPressGestureRecognizer with a UIPanGestureRecognizer.

The UIPanGestureRecognizer should start with a long press. Is there a simple way

相关标签:
6条回答
  • 2020-11-30 09:16

    actually, you don't have to combine gesture recognizers - you can do this solely with UILongPressGestureRecognizer... You enter StateBegan once your touch(es) have stayed within 'allowableMovement' for 'minimumPressDuration'. You stay in your continuous longPressGesture as long as you don't lift any of your fingers - so you can start moving your fingers and track the movement through StateChanged.

    Long-press gestures are continuous. The gesture begins (UIGestureRecognizerStateBegan) when the number of allowable fingers (numberOfTouchesRequired) have been pressed for the specified period (minimumPressDuration) and the touches do not move beyond the allowable range of movement (allowableMovement). The gesture recognizer transitions to the Change state whenever a finger moves, and it ends (UIGestureRecognizerStateEnded) when any of the fingers are lifted.

    0 讨论(0)
  • 2020-11-30 09:16

    For combinate more gesture :

    1. Create a local variable var shouldAllowSecondGesture : Bool = false
    2. Create the two recognizer

    let longPressRec = UILongPressGestureRecognizer(target: self, action: #selector(self.startDrag(sender:))) cell.addGestureRecognizer(longPressRec) let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(sender:))) cell.isUserInteractionEnabled = true cell.addGestureRecognizer(panGestureRecognizer)

    1. Extension your VC and implement GestureRecognizerDelegate for implemented this method.

      extension YourViewController : UIGestureRecognizerDelegate {

      func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
              return true
          }
      
      
      
      func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
               // We only allow the (drag) gesture to continue if it is within a long press
               if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) {
                   return false
               }
               return true
          }
      
      
      @objc func startDrag(sender:UIPanGestureRecognizer) {
      
          if(sender.state == .began) {
                  // handle the long press
              }
          else if(sender.state == .changed){
                  shouldAllowPan = true
      
              }
              else if (sender.state == .ended) {
                  shouldAllowPan = false
              }
          }
      
    0 讨论(0)
  • 2020-11-30 09:18

    Read the "Subclassing Notes" section of Apple's UIGestureRecognizer Class Reference at:

    https://developer.apple.com/library/prerelease/tvos/documentation/UIKit/Reference/UIGestureRecognizer_Class/

    0 讨论(0)
  • 2020-11-30 09:22

    Andy B's approach in Swift,

    1. Add the UIGestureRecognizerDelegate delegate to the class

      class ViewController: UIViewController, UIGestureRecognizerDelegate
      
    2. Add a member variable

      var shouldAllowPan: Bool = false
      
    3. Add the gestures and need to add the pan gesture delegate to the VC. This is needed to fire off the shouldRecognizeSimultaneouslyWithGestureRecognizer and gestureRecognizerShouldBegin functions

      // long press
      let longPressRec = UILongPressGestureRecognizer(target: self, action: "longPress:")
      yourView.addGestureRecognizer(longPressRec)
      
      // drag
      let panRec = UIPanGestureRecognizer(target: self, action: "draggedView:")
      panRec.delegate = self
      yourView.addGestureRecognizer(panRec)
      
    4. Allow simultaneous gestures

      func gestureRecognizer(UIGestureRecognizer,
      shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
          // println("shouldRecognizeSimultaneouslyWithGestureRecognizer");
          return true
      }
      
      func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
           // We only allow the (drag) gesture to continue if it is within a long press
           if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) {
               return false;
           }
           return true;
      }
      
    5. Inside the long press handler:

      func longPress(sender: UILongPressGestureRecognizer) {
      
          if(sender.state == .Began) {
              // handle the long press
          }
          else if(sender.state == .Changed){
              shouldAllowPan = true
      
          }
          else if (sender.state == .Ended) {
              shouldAllowPan = false
          }
      } 
      
    0 讨论(0)
  • 2020-11-30 09:34

    I found a solution: This UIGestureRecognizerDelegate method does exactly what I looked for:

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
    
    0 讨论(0)
  • 2020-11-30 09:38

    I had a bit of a hard time for this problem. The accepted answer wasn't enough. No matter what I put in that method the pan or longpress handlers would get invoked. A solution I found was as follows:

    1. Ensure the gesture recognizers' delegates are assigned to the same class (in my case self) and ensure the delegate class is a UIGestureRecognizerDelegate.
    2. Add the following delegate method to your class (as per the answer above):

      - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
      shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 
           return YES;
      }
      
    3. Add the following delegate method to your class:

      - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
           if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) {
                return NO;
           }
           return YES;
      }
      
    4. Then add either a property or ivar which will track if the pan should be allowed to begin (see method above). In my case BOOL shouldAllowPan.

    5. Set the BOOL to NO in your init or viewDidLoad. Inside your longPress handler set the BOOL to YES. I do it like this:

      - (void) longPressHandler: (UILongPressGestureRecognizer *) gesture {
      
           if(UIGestureRecognizerStateBegan == gesture.state) {
              shouldAllowPan = NO;
           }
      
           if(UIGestureRecognizerStateChanged == gesture.state) {
              shouldAllowPan = YES;
           }
      }
      
    6. Inside the panHandler I do a check on the BOOL:

      - (void)panHandler:(UIPanGestureRecognizer *)sender{
          if(shouldAllowPan) {
                // do your stuff
          }
      
    7. And finally reset the BOOL within the panHandler:

      else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
          shouldAllowPan = NO;
      }
      
    8. And then go grab a beer to congratulate yourself. ;)

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