UITapGestureRecognizer-단일 탭 및 이중 탭


156

UITapGestureRecognizers뷰 에 2를 추가하려고합니다 . 하나는 단일 탭이고 다른 하나는 더블 탭 이벤트입니다. 단일 탭 인식기가 예상대로 작동합니다 (자체적으로). 그러나 더블 탭 인식기가 작동하지 않는 것 같습니다.

유무과 같은 특성을 실험을 시도 : cancelsTouchesInView, delaysTouchesBegan그리고 delaysTouchesEnded하지만 여전히 작동하지 않습니다.

두 번 탭하면 싱글 탭 인식기가 항상 활성화되고 더블 탭 이벤트도 슈퍼 뷰로 전송됩니다. 그러나 사용자 정의 더블 탭 인식기는 전혀 알리지 않는 것 같습니다.

문서는 위에서 언급 한 3 가지 속성을 목적으로 사용할 수 있다고 제안합니다. 그러나 어떤 값을 설정해야하며 어떤 인식기 (싱글, 더블 또는 둘 다)인지 확실하지 않습니다. 이것에 익숙한 누군가가 도움이되기를 바랍니다.

다음은 최신 업데이트 코드 블록입니다.

// ****** 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
임의의 주석 : 변수 이름의 밑줄은 대부분 Objective-C 프로그래머를 울립니다. 더 나쁜 것은 변수 이름이 설명 적이 지 않다는 것입니다. 왜 singleTapRecognizer와 doubleTapRecognizer (또는 이와 유사한 것)를 사용하지 않습니까? 입력하는 데 약간의 시간이 걸리지 만 코드를 더 읽기 쉽게 만듭니다.
UIAdam

조언에 감사드립니다. 변수 이름이 더 설명 적이어야한다는 데 동의하십시오. 그러나이 특정 코드 세그먼트는 확정되지 않았으며 제안 된대로보다 세련되고 설명적인 코드를 게시 할 것입니다.
Stanley

다른 사람이 비슷한 문제가있는 경우. 이중 탭과 단일 탭 인식기가 신속하게 함께 작동하는 데 어려움을 겪었습니다 (싱글 탭은 잘 작동했지만 더블 탭은 없었습니다). 스토리 보드를 사용하여 인식기를 장면으로 드래그했습니다. viewDidLoad 내부에 처리기와 명령문이 있습니다. singleTapRecognizer.requireGestureRecognizerToFail (doubleTabRecognizer)이지만 여전히 두 번 탭하지 않습니다. 누락 된 퍼즐 조각은 더블 탭 인식기 아이콘을 장면의 맨 윗줄에서 더블 탭을 인식 해야하는 부분으로 드래그하는 것입니다.
Paulus

1
objc에서 개인 ivar 이름 앞에 밑줄을 사용하여 @UIAdam을 사용하는 것은 일반적이지 않습니까? (빠른 배경에서 온)
Charlton Provatas

답변:


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];

참고 : 당신이 사용하는 경우 numberOfTouchesRequired 가되어야한다 .numberOfTouchesRequired = 1;

스위프트

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)

답변 주셔서 감사합니다, 코드를 시도했지만 여전히 작동하지 않습니다. 여전히 놓친 것이 있어야합니다. 더 힌트가 있습니까?
Stanley

이것에 대한 구현 파일을 가질 수 있습니까?
Anil Kothari

@Stanley : Anils의 대답은 당신이 또한 핸들러 (doSingleTap, doDoubleTap)를 제공해야 물론 떨어져 작동합니다
한국 Jarc

단일 탭은 예상대로 작동하는 UITableView를 업데이트합니다. 더블 탭은 당분간 NSLog를 사용하여 로그 문을 출력합니다. 내 응답은 응답 체인에 대해 명시 적으로 아무것도하지 않았으므로 첫 번째 응답자 상태가 첫 번째 탭 후 UIView에서 다른 곳으로 이동한다는 것입니다.
Stanley

6
해결책이 저에게 효과적입니다. 단일 탭 선택기가 약간 지연된 후에 작동됩니다.
Vladimir Obrizan

46

스위프트 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)

코드 라인 singleTap.require (toFail : doubleTap)에서 우리는 싱글 탭을 기다리게하고 탭 이벤트가 더블 탭이 아닌지 확인합니다.


31

requireGestureRecognizerToFail : 메소드를 사용해야합니다. 이 같은:

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];


두 인식기 모두에서 "실패"메소드 호출을 다시 사용하려고했습니다. 그러나 여전히 작동하지 않습니다. 이전에 더블 탭 기능을 사용했다면 경험을 더 공유하십시오.
Stanley

1
나는이 정확한 코드 (Anil이 더 자세하게 게시 한 것과 동일)를 시도했으며 그것은 나를 위해 작동합니다.
UIAdam

의견을 주셔서 감사합니다, 그래도 내가 아직 놓친 뭔가가 있어야합니다 ...
Stanley

당신의 코드는 여전히 딜레이와 터치로 지연됩니다. Anil의 코드를 정확하게 따르도록하십시오. requireGestureRecognizerToFail을 한 번만 사용하십시오.
UIAdam 2012 년

오늘 또는 내일 나중에 조언하는대로 시간이 부족합니다. 친절한 지원에 감사드립니다 ...
Stanley

15

// ---- 먼저 더블 및 싱글 탭 제스처를 할당해야합니다 .-------- //

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];

// ----------------------- 탭수 ---------------- //

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

// -------보기 또는 버튼에 더블 탭 및 싱글 탭 제스처 추가 -------- //

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

10

그것이 정확히 당신이 찾고있는 것인지 확실하지 않지만 제스처 인식기가없는 싱글 / 더블 탭을했습니다. UITableView에서 사용하고 있으므로 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;

singleTap 및 doubleTap 메소드는 NSIndexPath를 매개 변수로 사용하여 void입니다.

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

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

그것이 도움이되기를 바랍니다.


답변 @Novarg에 감사드립니다. doubleTap 인식기에 대해 문제가 있습니까?
Stanley

@Stanley nope, singleTap은 0.2 초 동안 대기 중입니다. 그리고 두 번째 탭이 활성화 된 동안 singleTap 방법이 취소됩니다.
Novarg

도움을 주셔서 감사합니다. 오늘 또 시간이 없어 확실히 내일 시험 해볼까요 :)
Stanley

창의적인 답변;)
Michael

아주 좋은 해결책. 다음 터치도 인식되도록 각 처리기 (singleTap, doubleTap)에 tapCount = 0을 추가해야했습니다.
Sirio

3

스위프트 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

singleTap과 doubleTap을 모두 감지하기 위해 UIGestureRecognizerDelegate 메소드를 구현했습니다.

그냥하세요.

 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];

그런 다음 이러한 대리자 메서드를 구현하십시오.

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

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

0

일부보기에는 이중 탭 인식기가 내장되어 있습니다 ( MKMapView예제). 이 문제를 해결하려면 UIGestureRecognizerDelegate메소드 를 구현 shouldRecognizeSimultaneouslyWithGestureRecognizer하고 리턴 해야합니다 YES.

먼저 이중 및 단일 인식기를 구현하십시오.

// 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];

그런 다음 구현하십시오.

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

-1

@stanley의 의견을 참조하여-

탭 동작을 사용하여 선택을 행하기 위해 탭 동작을 사용하지 마십시오 UITableView.

그러나 단일 탭 동작 인식기에서 '보기에서 터치 취소'를 '아니요'로 설정해야합니다. 그렇지 않으면 탭 이벤트가 발생하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.