2012-10-30 136 views
6

我的UILongPressGestureRecognizer中的allowableMovement属性似乎被忽略。我使用Single View Application模板创建了一个新项目(Xcode 4.5.1,iOS 6),并在视图中添加了长按手势识别器。有一个连接线和一个动作。下面是操作方法的代码:allowableMovement似乎被忽略

- (IBAction)longPress:(UILongPressGestureRecognizer *)sender 
{  
    if (sender.state == UIGestureRecognizerStatePossible) NSLog(@"possible"); 
    if (sender.state == UIGestureRecognizerStateBegan)  NSLog(@"began"); 
    if (sender.state == UIGestureRecognizerStateChanged) NSLog(@"changed");  
    if (sender.state == UIGestureRecognizerStateRecognized) NSLog(@"recognized");  
    if (sender.state == UIGestureRecognizerStateCancelled) NSLog(@"cancelled"); 
    if (sender.state == UIGestureRecognizerStateFailed)  NSLog(@"failed"); 

    CGPoint locationInView = [sender locationInView:self.view]; 

    NSLog(@"long press: allowableMovement= %f, x= %f, y= %f", sender.allowableMovement, locationInView.x, locationInView.y); 
} 

如果我按下足够长的时间放手我在日志中得到这样的:

2012-10-30 20:24:41.449 Long Press[1078:907] began 
2012-10-30 20:24:41.455 Long Press[1078:907] long press: allowableMovement= 10.000000, x= 210.500000, y= 99.500000 
2012-10-30 20:24:42.880 Long Press[1078:907] recognized 
2012-10-30 20:24:42.882 Long Press[1078:907] long press: allowableMovement= 10.000000, x= 208.500000, y= 96.000000 

这是我所期望的那样。

但无论我将allowableMovement设置为(正面,负面,大,小),一旦状态为UIGestureRecognizerStateBegan,我就可以将手指拖到屏幕上。状态更改为UIGestureRecognizerStateChanged,并且频繁更新,并且locationInView继续准确跟踪。当我放手的时候,我得到了UIGestureRecognizerStateRecognized状态,并且最终输出到了日志中。

该类参考指出,如果移动超过allowableMovement,识别器将失败。为什么allowableMovement属性似乎被忽略?

回答

23

allowableMovement属性不是关于手势开始后您可以拖动多远。这是关于手势开始前你能移动多远。

从类参考:

手势开始(UIGestureRecognizerStateBegan)当已经按下的指定时段内(minimumPressDuration)容许手指(numberOfTouchesRequired)的数量和接触不移动超出容许范围运动(allowableMovement)。

当设置minimumPressDuration的东西高像3秒allowableMovement的东西等低1个像素,这变得明显。如果你的手指在所有手势上滚动,手势将不会开始。但是,如果将allowableMovement设置为100,则手指可以转动很多,手势将开始。

这样就像其他属性一样。他们都是关于手势开始所需的。

+0

@ Murray Sagal:这也解决了我的疑惑。想知道,如果有一种方法可以检测用户是否在LongPressGesture开始后将他们的手指拖出视图。 – Kashif

+0

@TPOS我认为你可以使用'locationInView:'或其中一种方法。但它听起来像是值得自己的问题。 –

4

我以为allowableMovement有这个目的。我做了一个小的子类来实现allowableMovementAfterBegan的“预期”行为。

#import <UIKit/UIKit.h> 
#import <UIKit/UIGestureRecognizerSubclass.h> 

@interface TDMLongPressGestureRecognizer : UILongPressGestureRecognizer 
@property (nonatomic, assign) CGFloat allowableMovementAfterBegan; 
@end 

@implementation TDMLongPressGestureRecognizer 
{ 
    CGPoint initialPoint; 
} 

- (instancetype)initWithTarget:(id)target action:(SEL)action 
{ 
    self = [super initWithTarget:target action:action]; 
    if (self) { 
     // Use default value for allowableMovement before touches begin 
     _allowableMovementAfterBegan = self.allowableMovement; 
    } 
    return self; 
} 

- (void)reset 
{ 
    [super reset];  
    initialPoint = CGPointZero; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesBegan:touches withEvent:event]; 
    initialPoint = [self locationInView:self.view]; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesMoved:touches withEvent:event]; 

    if (!CGPointEqualToPoint(initialPoint, CGPointZero)) 
    { 
     CGPoint currentPoint = [self locationInView:self.view]; 

     CGFloat distance = hypot(initialPoint.x - currentPoint.x, initialPoint.y - currentPoint.y); 
     if (distance > self.allowableMovementAfterBegan) 
      self.state = UIGestureRecognizerStateFailed; 
     } 
    } 
} 
+0

有趣。限制允许移动的用例是什么? –

+0

我用它在UIScrollView中对内容进行了长时间的压缩。 – duemunk

+0

刚刚碰到你指的情况 - 有一个UICollectionViewCell,我想添加一个手势识别器,但如果用户垂直滚动UICollectionView(这是默认情况下UITableView的工作方式),则取消手势。同样令我惊讶的是,允许移动并不意味着这一点,但这似乎是一个很好的解决方案,所以谢谢! –