UITapGestureRecognizer - chạm một lần và chạm hai lần


156

Tôi đang cố gắng thêm 2 UITapGestureRecognizersvào một chế độ xem, một cho một lần nhấn và một cho các sự kiện nhấn đúp. Bộ nhận dạng đơn chạm đang hoạt động như mong đợi (tự nó). Nhưng tôi dường như không thể làm cho bộ nhận dạng chạm kép hoạt động.

Có cố gắng thử nghiệm với những đặc tính như: cancelsTouchesInView, delaysTouchesBegandelaysTouchesEndednhưng vẫn không làm việc.

Khi tôi nhấn đúp, bộ nhận dạng một lần nhấn sẽ luôn được kích hoạt và sự kiện nhấn đúp cũng sẽ được gửi đến chế độ xem siêu. Nhưng bộ nhận dạng chạm kép tùy chỉnh dường như không được thông báo.

Tài liệu dường như gợi ý rằng 3 thuộc tính được đề cập ở trên có thể được sử dụng cho mục đích này. Nhưng tôi chỉ không chắc chắn những giá trị nào nên được đặt và trên (các) bộ nhận dạng nào (đơn, đôi hoặc cả hai). Hy vọng ai đó quen thuộc với điều này có thể giúp đỡ.

Sau đây là khối mã được cập nhật mới nhất.

// ****** gesture recognizers ******

- (void)addSingleAndDoubleTapGestureRecognizersToView:(UIView *)view
{
    // single tap    
    UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: tableViewController action: @selector(handleSingleTapOnView:)];                                 
    [singleTapRecognizer setNumberOfTouchesRequired:1];
    [view addGestureRecognizer: singleTapRecognizer];

    // double tap 
    UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: tableViewController action: @selector (handleDoubleTapOnView:)];        
    [doubleTapRecognizer setNumberOfTouchesRequired:2];         
    [singleTapRecognizer requireGestureRecognizerToFail: doubleTapRecognizer];
    [view addGestureRecognizer: doubleTapRecognizer];         
}

- (void)handleSingleTapOnView:(id)sender
{

}

- (void)handleDoubleTapOnView:(id)sender
{

}

30
Nhận xét ngẫu nhiên: dấu gạch dưới trong tên biến sẽ làm cho hầu hết các lập trình viên Objective-C co rúm lại. Điều tồi tệ hơn là tên biến của bạn không được mô tả. Tại sao không chỉ sử dụng singleTapRecognizer và doubleTapRecognizer (hoặc một cái gì đó tương tự)? Phải mất thêm một giây để nhập, nhưng làm cho mã của bạn dễ đọc hơn nhiều.
UIAdam

Cảm ơn lời khuyên, đồng ý với bạn rằng các tên biến nên được mô tả nhiều hơn. Nhưng đoạn mã đặc biệt này chưa được hoàn thiện và sẽ đăng mã mô tả và đánh bóng hơn như đề xuất ...
Stanley

Trong trường hợp bất cứ ai khác có một vấn đề tương tự. Tôi đã vật lộn để có được hai lần nhấn và các công cụ nhận biết một lần làm việc cùng nhau trong swift (một lần nhấn hoạt động tốt, nhưng không có chạm hai lần). Tôi kéo những người nhận ra cảnh đó bằng cách sử dụng bảng phân cảnh. Tôi đã có các trình xử lý và câu lệnh: singleTapRecognizer.requireGestureRecognizerToFail (doubleTabRecognizer) trong viewDidLoad của tôi, nhưng vẫn không chạm hai lần. Mảnh ghép còn thiếu của tôi là kéo biểu tượng nhận dạng chạm hai lần (từ hàng trên cùng của cảnh) qua phần chế độ xem mà chạm hai lần sẽ được nhận ra.
Paulus

1
@UIAdam sử dụng dấu gạch dưới để tiền tố một tên ngà riêng trong objc là khá phổ biến mặc dù không? (đến từ một nền tảng nhanh chóng)
Charlton Provatas

Câu trả lời:


412
UITapGestureRecognizer *singleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSingleTap)] autorelease];
singleTap.numberOfTapsRequired = 1; 
[self.view addGestureRecognizer:singleTap];

UITapGestureRecognizer *doubleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doDoubleTap)] autorelease];
doubleTap.numberOfTapsRequired = 2; 
[self.view addGestureRecognizer:doubleTap];

[singleTap requireGestureRecognizerToFail:doubleTap];

Lưu ý: Nếu bạn đang sử dụng numberOfTouchesRequired thì phải .numberOfTouchesRequired = 1;

Dành cho Swift

let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didPressPartButton))
singleTapGesture.numberOfTapsRequired = 1
view.addGestureRecognizer(singleTapGesture)

let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap))
doubleTapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTapGesture)

singleTapGesture.require(toFail: doubleTapGesture)

Cảm ơn câu trả lời, đã thử mã của bạn nhưng nó vẫn không hoạt động. Vẫn phải có một cái gì đó tôi đã bỏ lỡ. Bạn có thêm gợi ý nào không?
Stanley

Tôi có thể có tập tin thực hiện của bạn cho điều này?
Anil Kothari

@Stanley: Câu trả lời của Anils nên hoạt động, tất nhiên bạn cũng phải cung cấp trình xử lý (doSingleTap, doDoubleTap)
Rok Jarc

Một lần nhấn cập nhật một UITableView đang hoạt động như mong đợi. Chạm hai lần, trong thời gian hiện tại, chỉ cần xuất một câu lệnh log bằng NSLog. Sự nghi ngờ của tôi là trạng thái phản hồi đầu tiên đi từ UIView sang một nơi khác sau lần nhấn đầu tiên vì tôi chưa làm gì rõ ràng về chuỗi phản hồi.
Stanley

6
Các giải pháp làm việc cho tôi. Bộ chọn một lần nhấn được kích hoạt sau một số độ trễ.
Vladimir Obrizan

46

Giải pháp Swift 3:

let singleTap = UITapGestureRecognizer(target: self, action:#selector(self.singleTapAction(_:)))
singleTap.numberOfTapsRequired = 1
view.addGestureRecognizer(singleTap)

let doubleTap = UITapGestureRecognizer(target: self, action:#selector(self.doubleTapAction(_:)))
doubleTap.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTap)

singleTap.require(toFail: doubleTap)

Trong dòng mã singleTap.require (toFail: doubleTap), chúng tôi buộc một lần nhấn phải chờ và đảm bảo rằng sự kiện nhấn không phải là chạm hai lần.


31

Bạn cần sử dụng phương thức notifyGestureRecognizerToFail :. Một cái gì đó như thế này:

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];


Đã thử sử dụng cuộc gọi phương thức "Thất bại" với cả hai bộ nhận dạng một lần nữa. Nhưng vẫn không hoạt động. Nếu bạn đã có một lần chạm hai lần hoạt động trước đây, xin vui lòng chia sẻ thêm một số kinh nghiệm của bạn với tôi.
Stanley

1
Tôi đã thử mã chính xác này (giống như những gì Anil đã đăng chi tiết hơn) và nó hoạt động với tôi.
UIAdam

Cảm ơn vì nhận xét, sau đó vẫn phải có một cái gì đó mà tôi đã bỏ lỡ ...
Stanley

Mã của bạn vẫn bị rối với độ trễTouches và không có gì. Làm cho nó chính xác theo mã của Anil. Chỉ sử dụng allowGestureRecognizerToFail một khi chúng ta có nó.
UIAdam

Sẽ làm như bạn khuyên sau hôm nay hoặc ngày mai vì tôi sắp hết thời gian. Cảm ơn sự giúp đỡ của bạn ...
Stanley

15

// ---- trước tiên, bạn phải phân bổ cử chỉ chạm hai lần và một lần ------- //

UITapGestureRecognizer* doubleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : @selector (handleDoubleTap:)];

UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : @selector (handleSingleTap:)];

[singleTap requireGestureRecognizerToFail : doubleTap];
[doubleTap setDelaysTouchesBegan : YES];
[singleTap setDelaysTouchesBegan : YES];

// ----------------------- số lần nhấn ---------------- //

[doubleTap setNumberOfTapsRequired : 2];
[singleTap setNumberOfTapsRequired : 1];

// ------- thêm thao tác chạm hai lần và nhấn một lần vào chế độ xem hoặc nút -------- //

[self.view addGestureRecognizer : doubleTap];
[self.view addGestureRecognizer : singleTap];

10

Không chắc đó có chính xác là những gì bạn đang tìm kiếm không, nhưng tôi đã thực hiện một lần chạm đơn / đôi mà không cần nhận dạng cử chỉ. Tôi đang sử dụng nó trong UITableView, vì vậy tôi đã sử dụng mã đó trong phương thức didSelectRowAtIndexPath

    tapCount++;
    switch (tapCount)
    {
        case 1: //single tap
            [self performSelector:@selector(singleTap:) withObject: indexPath afterDelay: 0.2];
            break;
        case 2: //double tap
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTap:) object:indexPath];
            [self performSelector:@selector(doubleTap:) withObject: indexPath];
            break;
        default:
            break;
    }
    if (tapCount>2) tapCount=0;

Các phương thức singleTap và doubleTap không có giá trị với NSIndexPath như một tham số:

- (void)singleTap:(NSIndexPath *)indexPath {
  //do your stuff for a single tap
}

- (void)doubleTap:(NSIndexPath *)indexPath {
  //do your stuff for a double tap
}

Hy vọng nó giúp


Cảm ơn câu trả lời, @Novarg. Bạn có gặp vấn đề tôi gặp phải về bộ nhận dạng doubleTap không?
Stanley

@Stanley không, singleTap đang đợi 0,2 giây trước khi bắn. Và nếu trong thời gian trung bình, lần nhấn thứ hai được kích hoạt, thì phương thức singleTap sẽ bị hủy.
Novarg

Có vẻ rất hứa hẹn, nhờ sự giúp đỡ của bạn. Đang hết thời gian hôm nay một lần nữa. Chắc chắn sẽ thử nó vào ngày mai :)
Stanley

Câu trả lời sáng tạo;)
Michael

giải pháp rất tốt. Tôi chỉ cần thêm tapCount = 0 trên mỗi trình xử lý (singleTap, doubleTap) để đảm bảo rằng các lần chạm sau cũng được nhận ra.
Sirio

3

Giải pháp cho Swift 2:

let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
singleTapGesture.numberOfTapsRequired = 1 // Optional for single tap
view.addGestureRecognizer(singleTapGesture)

let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
doubleTapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTapGesture)

singleTapGesture.requireGestureRecognizerToFail(doubleTapGesture)

1

Tôi đã triển khai các phương thức UIGestureRecognizerDelegate để phát hiện cả singleTap và doubleTap.

Chỉ cần làm điều này.

 UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTapGesture:)];
    [doubleTap setDelegate:self];
    doubleTap.numberOfTapsRequired = 2;
    [self.headerView addGestureRecognizer:doubleTap];

    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleSingleTapGesture:)];
    singleTap.numberOfTapsRequired = 1;
    [singleTap setDelegate:self];
    [doubleTap setDelaysTouchesBegan:YES];
    [singleTap setDelaysTouchesBegan:YES];
    [singleTap requireGestureRecognizerToFail:doubleTap];
    [self.headerView addGestureRecognizer:singleTap];

Sau đó thực hiện các phương pháp đại biểu này.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
    return  YES;
}

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

0

Một số chế độ xem có bộ nhận dạng chạm kép được tích hợp ( MKMapViewlà một ví dụ). Để giải quyết vấn đề này, bạn sẽ cần thực hiện UIGestureRecognizerDelegatephương thức shouldRecognizeSimultaneouslyWithGestureRecognizervà trả về YES:

Đầu tiên thực hiện nhận dạng kép và đơn của bạn:

// setup gesture recognizers
UITapGestureRecognizer* singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                action:@selector(mapViewTapped:)];
singleTapRecognizer.delegate = self;
singleTapRecognizer.numberOfTapsRequired = 1;


UITapGestureRecognizer* doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                      action:@selector(mapViewDoubleTapped:)];
doubleTapRecognizer.delegate = self;    // this allows
doubleTapRecognizer.numberOfTapsRequired = 2;
[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];

Và sau đó thực hiện:

#pragma mark UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer
*)otherGestureRecognizer {  return YES; }

-1

Liên quan đến bình luận của @ stanley -

Không thử và sử dụng cử chỉ nhấn để lựa chọn hàng để hoạt động UITableViewvì nó đã xử lý toàn bộ thao tác nhấn ....

Nhưng bạn phải đặt 'Hủy chạm trong Chế độ xem' thành 'KHÔNG' trên các nhận dạng cử chỉ nhấn duy nhất của mình nếu không sẽ không nhận được các sự kiện nhấn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.