iPhone iOS how to add a UILongPressGestureRecognizer and UITapGestureRecognizer to the same control and prevent conflict?

前端 未结 5 487
伪装坚强ぢ
伪装坚强ぢ 2021-02-01 19:25

I\'m building an iPhone app that would let the user rearrange some of the UI elements on the screen.

How can I add a tap gesture recognizer and a long press gesture rec

相关标签:
5条回答
  • 2021-02-01 19:43

    To combine successfully both you need:

    1º Add to interface gesture delegate at header

    @interface ViewController : ViewController <UIGestureRecognizerDelegate>
    

    2º Create gesture events and add to a view into source file:

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touch:)];
        [tap setNumberOfTapsRequired:1]; // Set your own number here
        [tap setDelegate:self]; // Add the <UIGestureRecognizerDelegate> protocol
    
        UILongPressGestureRecognizer *longTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longTouch:)];
        [longTap setNumberOfTapsRequired:0]; // Set your own number here
        [longTap setMinimumPressDuration:1.0];
        [longTap setDelegate:self]; // Add the <UIGestureRecognizerDelegate> protocol
        [tap requireGestureRecognizerToFail:longTap];   // Priority long
    
        [self.view addGestureRecognizer:tap];
        [self.view addGestureRecognizer:longTap];
    

    3º Add callbacks in source file:

    - (void) touch: (UITapGestureRecognizer *)recognizer
    {
        CGPoint location = [recognizer locationInView: self.HUDview];
        if (recognizer.state == UIGestureRecognizerStateBegan)
        {
            NSLog(@"touch UIGestureRecognizerStateBegan");
        }
        if (recognizer.state == UIGestureRecognizerStateEnded)
        {
            NSLog(@"touch UIGestureRecognizerStateEnded");
            //NSLog(@"Position of touch: %.3f, %.3f", location.x, location.y);    // Position landscape
        }
    }
    
    - (void) longTouch: (UILongPressGestureRecognizer *)recognizer
    {
        if (recognizer.state == UIGestureRecognizerStateBegan)
        {
            NSLog(@"longTouch UIGestureRecognizerStateBegan");
        }
        if (recognizer.state == UIGestureRecognizerStateEnded)
        {
            NSLog(@"longTouch UIGestureRecognizerStateEnded");
        }
    }
    

    4º Set gesture recognizer available:

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
    {
        return YES;
    }
    
    0 讨论(0)
  • 2021-02-01 19:45

    To allow both gestures to work together, implement the following delegate method:

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

    To make it so that the long press has first priority, do:

    [tapGesture requireGestureRecognizerToFail:longPress];

    0 讨论(0)
  • 2021-02-01 19:48

    As an alternative approach, don't have two separate recognisers - just use the LongPress recogniser for both events:

    Configure as follows:

    UILongPressGestureRecognizer* longPress = [ [ UILongPressGestureRecognizer alloc ] initWithTarget:self.nextResponder action:@selector(longPressEvent:)];
        categoryPanelDrag.minimumPressDuration = 0.0;
    

    Then handle as follows:

    - (BOOL)longPressEvent:(UILongPressGestureRecognizer *)gesture {
    
        // _dragStarted is a class-level BOOL
    
        if(UIGestureRecognizerStateBegan == gesture.state) {
            _dragStarted = NO;
        }
    
        if(UIGestureRecognizerStateChanged == gesture.state) {
            _dragStarted = YES;
            // Do dragging stuff here
        }
    
        if(UIGestureRecognizerStateEnded == gesture.state) {
    
            if (_dragStarted == NO)
            {
                // Do tap stuff here
    
            }
            else
            {
                // Do drag ended stuff here
            }
        }
    
        return YES;
    
    }
    
    0 讨论(0)
  • 2021-02-01 19:56

    You could take care of it in the code, that during the long press, set a flag, and if the tap gets called while the flag is true or whatever then don't execute the tap code and reset the flag. I don't know a better way

    0 讨论(0)
  • 2021-02-01 20:04

    I did try moby and journeyman's approach but somehow they didn't fit my project well, so I solved like below,

    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
        NSLog(@"%@ %ld",touch.description, touch.phase);
        [self performSelector:@selector(checkTouch:) withObject:touch afterDelay:0.5];
        return YES;
    }
    

    and

    - (void)checkTouch:(UITouch *)touch{
        NSLog(@"touch phase = %ld",touch.phase);
        if (touch.phase == UITouchPhaseStationary) {
            //still holding my hand and this means I wanted longPressTouch
        }
        if (touch.phase == UITouchPhaseEnded){
            //I released my finger so it's obviously tap 
        }
    }
    

    It could be simpler solution but of course it depends to project.

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