Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining a UILongPressGestureRecognizer with a UIPanGestureRecognizer

Tags:

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

The UIPanGestureRecognizer should start with a long press. Is there a simple way to do this? or do I really have to write my own gesture recognizer?

I wan't something like on the home screen. You press on an icon and after some time the icons start wobbling. Afterwards without releasing my finger from the screen I can start dragging the icon under my finger around.

like image 456
V1ru8 Avatar asked Aug 16 '10 10:08

V1ru8


2 Answers

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.

like image 81
annie Avatar answered Sep 20 '22 03:09

annie


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. ;)

like image 20
Andy B Avatar answered Sep 19 '22 03:09

Andy B