2012-10-30 134 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的工作方式),則取消手勢。同樣令我驚訝的是,允許移動並不意味着這一點,但這似乎是一個很好的解決方案,所以謝謝! –