제스처 인식기 및 버튼 동작


99

다음과 같은 뷰 계층 구조가 있습니다.

UIView (A)
UIView > UIImageView
UIView > UIView (B)
UIView > UIView (B) > Rounded Rect Button
UIView > UIView (B) > UIImageView
UIView > UIView (B) > UILabel

UIView (B)에 제스처 인식기를 연결했습니다. 내가 직면 한 문제는 UIView (B) 내부에있는 둥근 사각형 버튼에 대한 작업을 얻지 못한다는 것입니다. singleTap 제스처 인식기는 버튼의 Touch Up Inside 이벤트를 캡처 / 무시합니다.

어떻게 작동시킬 수 있습니까? 나는 응답자 체인 계층 구조가 버튼 터치 이벤트에 우선권을 부여하고 트리거 될 것이라고 생각했습니다! 내가 무엇을 놓치고 있습니까?

다음은 관련 코드입니다.

#pragma mark -
#pragma mark View lifecycle (Gesture recognizer setup)

- (void)viewDidLoad {
    [super viewDidLoad];

    // double tap gesture recognizer
    UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)];
    dtapGestureRecognize.delegate = self;
    dtapGestureRecognize.numberOfTapsRequired = 2;
    [self.viewB addGestureRecognizer:dtapGestureRecognize];

    // single tap gesture recognizer
    UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)];
    tapGestureRecognize.delegate = self;
    tapGestureRecognize.numberOfTapsRequired = 1;
    [tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize];
    [self.viewB addGestureRecognizer:tapGestureRecognize];

    // add gesture recodgnizer to the grid view to start the edit mode
    UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)];
    pahGestureRecognizer.delegate = self;
    pahGestureRecognizer.minimumPressDuration = 0.5;
    [self.viewB addGestureRecognizer:pahGestureRecognizer];

    [dtapGestureRecognize release];
    [tapGestureRecognize release];
    [pahGestureRecognizer release];
}

#pragma mark -
#pragma mark Button actions

- (IBAction)buttonTouchUpInside:(id)sender {
    NSLog(@"%s, %@", __FUNCTION__, sender);
}

#pragma mark -
#pragma mark Gesture recognizer actions


- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    NSLog(@"%s", __FUNCTION__);
}

- (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    NSLog(@"%s", __FUNCTION__);
}

- (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer {

    switch (gestureRecognizer.state) {

        case UIGestureRecognizerStateEnded: {
            NSLog(@"%s", __FUNCTION__);

            break;
        }
        default:
            break;
    }
}

가장 간단한 방법은 cancelsTouchesInView = false를 설정하는 것입니다.
Bagusflyer 2017-06-02

답변:


176

"shouldReceiveTouch"메소드에서 터치가 버튼에 있으면 NO를 반환하는 조건을 추가해야합니다.

이것은 apple SimpleGestureRecognizers 예제 에서 가져온 것 입니다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

    // Disallow recognition of tap gestures in the segmented control.
    if ((touch.view == yourButton)) {//change it to your condition
        return NO;
    }
    return YES;
}

도움이 되길 바랍니다

편집하다

Daniel이 언급했듯이 UIGestureRecognizerDelegate작동 하려면 준수해야합니다 .

샤니


1
아 !!! 예,이 -gestureRecognizer : shouldReceiveTouch : 메소드를 잊어 버렸습니다. 올바른 방향을 알려 주셔서 감사합니다. 이것이 내 문제를 해결하지만 여전히이 경우 응답자 계층이 작동하지 않는 이유를 모르겠습니다. 아마도 그래야 할 것이지만 Apple에서 처리하지 않습니다.
Mustafa

2
UIGestureRecognizer 동작은 "정상"응답자 체인과 별개로 명확하게 설명됩니다. 이것은 Apple의 디자인 결정입니다.
Sylvain G.

11
UIGestureRecognizerDelegate 프로토콜을 준수하고 UIGestureRecognizer의 대리자를 해당 개체로 설정해야합니다.
Daniel

2
더 광범위하게 사용하려면 Ramesh 또는 flypig의 테스트 절에 대한 몇 가지 변형을 고려하십시오. 예를 들어, 제 경우에는 다음과 같은 줄로 끝났습니다. if ( [touch.view isKindOfClass:[UIControl class]] || [[touch.view superview] isKindOfClass:[UITableViewCell class]] ) {... tableview 셀은 private 클래스의 구성원 인 contentView에서 "손상"되므로 대신 superview의 클래스를 확인합니다.
clozach

답변 감사합니다! 제 경우에는 같은 문제가 발생했지만 실제 장치에서 테스트 할 때까지만 발견했습니다. 이 답변에 표시된대로 UIGestureDelegate를 사용하지 않고 시뮬레이터에서 앱을 실행하면 예상대로 잘못 작동했습니다.
Luis Artola 2013 년

51

나는 또한 같은 문제가 있었고, 나는 시도했다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{

    if ([touch.view isKindOfClass:[UIButton class]]) {      //change it to your condition
        return NO;
    }
    return YES;
}

이제 완벽하게 작동합니다 .........


4
나는 단지 놓친myGestureRecognizer.delegate = self;
zero3nna

20

일반적으로 모든 종류의 UIControl에서 터치를 피하기 위해 아래 delegate 메서드를 사용합니다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (([touch.view isKindOfClass:[UIControl class]])) {
         return NO;
    }
    return YES;
}

참고 : gestureRecognizerShouldBegin을 확인하지 마십시오 (recogniser.view 클래스 유형 확인). 작동하지 않습니다.


11

다음은 Swift 3.0 버전입니다.

extension UIViewController: UIGestureRecognizerDelegate {

public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    if touch.view is UIButton {
        return false
    }
    return true
}

잊지 마세요 :

Make your tapper object delegate to self (e.g: tapper.delegate = self)


6

다음은 Swift 버전입니다.

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if (touch.view!.isKindOfClass(UIButton)) {
        return false
    }
    return true
}

잊지 마세요 :

  1. 수업을 준수하도록 UIGestureRecognizerDelegate
  2. (예 :자가에 캐처 객체의 대리자를 확인 tapper.delegate = self)

5

가장 좋은 해결책은 아래 코드 스 니펫을 사용하는 것입니다.

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint touchLocation = [touch locationInView:self.view];
    return !CGRectContainsPoint(self.menuButton.frame, touchLocation);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.