2012-10-30 33 views
6

Thuộc tính allowableMovement trong số UILongPressGestureRecognizer dường như bị bỏ qua. Tôi đã tạo một dự án mới (Xcode 4.5.1, iOS 6) bằng cách sử dụng mẫu Ứng dụng xem đơn và thêm Trình nhận dạng cử chỉ báo chí dài vào chế độ xem. Có một ổ cắm có dây và một hành động. Dưới đây là các mã cho phương thức hành động:allowableMovement có vẻ bị bỏ qua

- (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); 
} 

Nếu tôi nhấn đủ dài và buông tôi có được điều này trong nhật ký:

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 

Đây là những gì tôi mong đợi.

Nhưng không có vấn đề gì tôi đặt allowableMovement thành (dương, âm, lớn, nhỏ), khi trạng thái là UIGestureRecognizerStateBegan, tôi có thể kéo ngón tay trên màn hình. Trạng thái thay đổi thành UIGestureRecognizerStateChanged và có các cập nhật thường xuyên và vị tríInView tiếp tục theo dõi chính xác. Khi tôi cho đi, tôi nhận được trạng thái UIGestureRecognizerStateRecognized và kết quả cuối cùng cho nhật ký.

Tham chiếu lớp cho biết trình nhận dạng sẽ thất bại nếu chuyển động vượt quá allowableMovement. Tại sao thuộc tính allowableMovement dường như bị bỏ qua?

Trả lời

23

Thuộc tính allowableMovement không phải là khoảng cách bạn có thể kéo sau khi cử chỉ đã bắt đầu. Đó là khoảng cách bạn có thể di chuyển trước khi cử chỉ bắt đầu.

Từ tham chiếu lớp:

Các cử chỉ bắt đầu (UIGestureRecognizerStateBegan) khi số lượng các ngón tay cho phép (numberOfTouchesRequired) đã được ép cho thời hạn quy định (minimumPressDuration) và chạm không di chuyển vượt ra ngoài phạm vi cho phép của phong trào (allowableMovement).

Điều này trở nên rõ ràng khi bạn đặt minimumPressDuration thành thứ gì đó cao như 3 giây và allowableMovement thành thứ gì đó thấp như 1 pixel. Nếu ngón tay của bạn cuộn ở tất cả các cử chỉ sẽ không bắt đầu. Nhưng nếu bạn đặt allowableMovement thành 100 ngón tay của bạn có thể cuộn xung quanh một chút và cử chỉ sẽ bắt đầu.

Bằng cách này, nó giống như các thuộc tính khác. Họ là tất cả về những gì được yêu cầu cho các cử chỉ để bắt đầu.

+0

@ Murray Sagal: Điều này cũng giải quyết được sự nhầm lẫn của tôi. Tự hỏi, nếu có một cách để phát hiện nếu người dùng kéo ngón tay của họ ra khỏi khung nhìn sau khi LongPressGesture bắt đầu. – Kashif

+0

@TPos Tôi nghĩ bạn có thể sử dụng 'locationInView:' hoặc một trong các phương pháp như nó. Nhưng có vẻ như nó sẽ xứng đáng với câu hỏi của chính nó. –

4

Tôi nghĩ allowableMovement có mục đích chính xác. Tôi đã tạo một phân lớp nhỏ để thực hiện hành vi "mong đợi" với một số 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

Thú vị. Trường hợp sử dụng của bạn là gì để hạn chế chuyển động được phép? –

+0

Tôi đã sử dụng nó để nhấn và giữ nội dung trong UIScrollView. – duemunk

+0

Chỉ cần chạy vào trường hợp bạn đang đề cập đến - có UICollectionViewCell mà tôi muốn thêm trình nhận dạng cử chỉ vào, nhưng hủy cử chỉ nếu người dùng cuộn UICollectionView theo chiều dọc (đây là cách UITableView hoạt động theo mặc định). Nó cũng gây ngạc nhiên cho tôi rằng allowableMovement không có nghĩa là như vậy, nhưng điều này có vẻ như một giải pháp tuyệt vời vì vậy cảm ơn! –

Các vấn đề liên quan