Дії розпізнавача жестів та кнопок


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 = брехня
Bagusflyer

Відповіді:


176

У методі "shouldReceiveTouch" слід додати умову, яка поверне "НІ", якщо натискання кнопки.

Це на прикладі яблучного 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;
}

сподіваюся, що це допоможе

Редагувати

Як зазначив Даніель, ви повинні відповідати, щоб UIGestureRecognizerDelegateце працювало.

шані


1
Ах !!! Так, я забув про цей -gestureRecognizer: shouldReceiveTouch: метод. Дякую, що вказали на мене в правильному напрямку. Хоча це і вирішує мою проблему, але я досі не знаю, чому ієрархія респондентів не працює в цьому випадку. Це, мабуть, повинно, але Apple цим не займається.
Мустафа

2
Поведінка UIGestureRecognizer чітко описується як окрема від "нормальної" ланцюга реагування. Це дизайнерське рішення від Apple.
Sylvain G.

11
Не забудьте відповідати протоколу UIGestureRecognizerDelegate та встановити делегат UIGestureRecognizer до цього об'єкта.
Даніель

2
Для ширшого використання розглянемо якийсь варіант із тестових статей Рамеша або flypig. У моєму випадку, наприклад, я закінчився рядком: if ( [touch.view isKindOfClass:[UIControl class]] || [[touch.view superview] isKindOfClass:[UITableViewCell class]] ) {... Зауважте, що комірки tableview "торкаються" у своєму contentView, який є членом приватного класу, тому ми перевіряємо замість цього класу нагляду.
clozach

Дякую за відповідь! У моєму випадку я зіткнувся з тією ж проблемою, але я виявив її лише до тих пір, поки не перевірив фактичний пристрій. Запуск програми в тренажері без використання UIGestureDelegate, як зазначено у цій відповіді, працював так, як очікувалося, хоча й неправильно.
Луїс Артола

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

Взагалі ми використовуємо метод делегування нижче, щоб уникнути дотику до всіх видів UIControls:

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

Примітка: НЕ робіть цю перевірку (перевірте тип класу prepoznaє.вигляд) gestureRecognizerShouldBegin, він не працюватиме.


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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.