滑动和长按相结合

时间:2012-12-05 15:31:38

标签: ios uigesturerecognizer

我正在尝试在我的ViewController(有一个tableView)中实现两个必须一个接一个地工作的手势识别器。第一个是向下滑动手势,第二个是长按手势。

这是我用@sergio建议修改的代码

    - (void)viewDidLoad
    {
        [super viewDidLoad];

        swipeDown = [[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDownAction)] autorelease];

        longPress = [[[CustomLongPress alloc]initWithTarget:self action:@selector(longPressAction)] autorelease];


        longPress.minimumPressDuration = 2;

        swipeDown.numberOfTouchesRequired = 1;

        swipeDown.direction = UISwipeGestureRecognizerDirectionDown;


       swipeDown.delegate = self ;

        longPress.delegate = self ;

        [myTableView addGestureRecognizer:swipeDown];

        [myTableView addGestureRecognizer:longPress];





  }


    -(void)swipeDownAction {

        _methodHasBeenCalled = YES;    // bool @property declared in .h

        NSLog(@"Swipe down detected");


    }



    -(void)longPressAction {

        NSLog(@"long press detected");
    }

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

我的UILongPressGestureRecognizer子类:

#import "CustomLongPress.h"
#import "ViewController.h"


@interface CustomLongPress()
{

    ViewController *vc;
}

@end


@implementation CustomLongPress
-(id)initWithTarget:(id)target action:(SEL)action controller:(ViewController *)viewCon
{
    self = [super initWithTarget:target action:action];

    if (self) {

        vc = viewCon;

    }

    return self;
}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
     NSLog(vc.methodHasBeenCalled ? @"Yes" : @"No");

    if (vc.methodHasBeenCalled) {

        [super touchesBegan:touches withEvent:event];
    }
}

不幸的是,我仍然只从swipeDown获取日志,但是当涉及到longPress时没有日志

2 个答案:

答案 0 :(得分:1)

为此你需要创建自己的自定义手势识别器。最好的方法是让你继续UILongPressGestureRecognizer,并在刷卡结束后让它“接受”长按。例如,在touchesBegan方法

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
   <if swipe recognizer action method has been called>
       [super touchesBegan:touches withEvent:event];
   }
}

通过这种方式,两个手势识别器都会尝试识别手势:滑动识别器会立即这样做;而自定义识别器会“等待”滑动识别器触发。

实现条件<if swipe recognizer action method has been called>的简单方法是在滑动操作中设置全局标记(在执行滑动操作时设置它;然后自定义识别器读取其值)。这是 easy ,到目前为止还不是您能找到的最佳实现。

另一种方法是依靠requiresGestureRecognizerToFail链接3个标准手势识别器,我们称之为A,B和C,其中:

  1. A是UISwipeGestureRecognizer;
  2. C是UILongPressGestureRecognizer;
  3. B是任何手势识别器。
  4. 您可以像这样配置它们:

    C --> B --> A
    

    x --> y表示x要求y失败。因此,您C(您的长按手势识别器)将需要B GR失败并且B要求A(您的滑动识别器)失败;只要B识别出滑动,A就会失败;一旦B失败,C将被允许识别长按(如果有的话)。

    编辑:

    阅读完您的评论后,您是否介意尝试一下,看看是否有帮助:

    1. 删除被覆盖的touchesBegan并将其替换为:

      - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
      }
      
    2. 然后定义:

      - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
      
        if (vc.methodHasBeenCalled) {
          [super touchesBegan:touches withEvent:event];
        } else {
           return;
        }
      }
      
    3. 如果这不起作用,那么让自定义手势识别器继承自通用手势识别器和

      1. 保留touchesBegan:并将touchesMoved替换为:

        - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
        
          self.lastTouch = [touches anyObject];
          if (vc.methodHasBeenCalled && self.gestureNotBegunYet == YES) {
            self.gestureNotBegunYet = NO;
            [self performSelector:@selector(recognizeLongPress) withObject:nil afterDelay:1.0];
        
          } else {
             return;
          }
        }
        
      2. 并添加:

        - (float)travelledDistance {
          CGPoint currentLocation = [self.lastTouch locationInView:self.view.superview];
          return sqrt(pow((currentLocation.x - self.initialLocation.x), 2.0) +
                    pow((currentLocation.y - self.initialLocation.y), 2.0));
        }
        
        - (void)fail {
          self.gestureNotBegunYet = YES;
          [NSObject cancelPreviousPerformRequestsWithTarget:self];
        
        }
        
        - (void)recognizeLongPress {
        
          if ([self travelledDistance] < kTapDragThreshold) {
            self.longPressed = YES;
            self.state = UIGestureRecognizerStateChanged;
          } else {
                [self fail];
                self.state = UIGestureRecognizerStateFailed;
          }
        }
        
        - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
          [self fail];
          [super touchesEnded:touches withEvent:event];
        }
        
        - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
          [self fail];
          [super touchesCancelled:touches withEvent:event];
        }
        

        您需要在.h

        中定义
        @property(nonatomic) CGPoint initialLocation;
        @property(nonatomic, retain) UITouch* lastTouch;
        @property(nonatomic) BOOL gestureNotBegunYet;
        

答案 1 :(得分:0)

如果我没有弄错的话,一旦系统检测到特定类型的手势(轻击,轻扫,平移,长按等),它就不能再为该触摸动作发送不同类型的手势。

这并不妨碍您达到预期的效果。也许是重载以下UIResponder方法的组合:

– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
– touchesCancelled:withEvent:

使用手势识别器(不确定输入是否被一个人消耗而被其他人忽略),您可以确定它是“长扫描”