8

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

- (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属性似乎被忽略了?

4

2 回答 2

29

allowableMovement属性与手势开始后可以拖动多远无关。这是关于在手势开始之前您可以移动多远。

从类参考:

当允许的手指数量 (numberOfTouchesRequired) 在指定的时间 (minimumPressDuration) 内被按下并且触摸没有超出允许的移动范围 (allowableMovement) 时,手势开始 (UIGestureRecognizerStateBegan)。

当您设置minimumPressDuration为像 3 秒这样的高值和allowableMovement像 1 像素这样的低值时,这一点变得很明显。如果您的手指完全滚动,则手势将不会开始。但是,如果您设置allowableMovement为 100,您的手指可以滚动很多,并且手势将开始。

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

于 2012-10-31T14:13:22.660 回答
6

我以为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;
        }
    }
}
于 2014-01-13T22:28:19.580 回答