Как отменить UIGestureRecognizer, если нажата кнопка subview

#iphone #cocoa-touch #uibutton #uigesturerecognizer

#iPhone #cocoa-touch #uibutton #uigesturerecognizer

Вопрос:

Я изо всех сил пытаюсь добиться желаемого поведения от устройств распознавания жестов, в частности, отмены определенных жестов, если сработали другие.

У меня есть ScrollView, настроенный на подкачку, и несколько подпросмотров на каждой странице. Я добавил распознаватель сенсорных жестов для перехода к следующей или предыдущей странице, если пользователь нажимает справа или слева от страницы.

     // Add a gesture recogniser turn pages on a single tap at the edge of a page
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureHandler:)];
    tapGesture.cancelsTouchesInView = NO;
    [self addGestureRecognizer:tapGesture];
    [tapGesture release];
  

и мой обработчик жестов:

 - (void) tapGestureHandler:(UIGestureRecognizer *) gestureRecognizer {
    const CGFloat kTapMargin = 180;

    // Get the position of the point tapped in the window co-ordinate system
    CGPoint tapPoint = [gestureRecognizer locationInView:nil];

    // If the tap point is to the left of the page then go back a page
    if (tapPoint.x > (self.frame.size.width - kTapMargin)) [self scrollRectToVisible:pageViewRightFrame animated:YES];

    // If the tap point is to the right of the page then go forward a page
    else if (tapPoint.x < kTapMargin) [self scrollRectToVisible:pageViewLeftFrame animated:YES];
}
  

Все работает хорошо, за исключением того, что у меня есть subview на странице, на которой есть кнопки. Я хочу иметь возможность игнорировать нажатие для поворота страницы, если пользователь нажимает кнопку в subView, и я не могу понять, как это сделать.

Приветствия

Дэйв

Ответ №1:

Решение, которое в итоге сработало для меня лучше всего, состояло в том, чтобы использовать hitTest, чтобы определить, есть ли какие-либо кнопки под местоположением жеста касания. Если есть, то просто игнорируйте остальной код жеста.

Кажется, работает хорошо. Хотелось бы знать, есть ли какие-либо ошибки в том, что я сделал.

 - (void) tapGestureHandler:(UIGestureRecognizer *) gestureRecognizer {
    const CGFloat kTapMargin = 180;

    // Get the position of the point tapped in the window co-ordinate system
    CGPoint tapPoint = [gestureRecognizer locationInView:nil];

    // If there are no buttons beneath this tap then move to the next page if near the page edge
    UIView *viewAtBottomOfHeirachy = [self.window hitTest:tapPoint withEvent:nil];
    if (![viewAtBottomOfHeirachy isKindOfClass:[UIButton class]]) {

        // If the tap point is to the left of the page then go back a page
        if (tapPoint.x > (self.bounds.size.width - kTapMargin)) [self scrollRectToVisible:pageViewRightFrame animated:YES];

        // If the tap point is to the right of the page then go forward a page
        else if (tapPoint.x < kTapMargin) [self scrollRectToVisible:pageViewLeftFrame animated:YES];
    }   
}
  

Комментарии:

1. Это лучший способ, который я мог представить для решения проблемы. Отлично!

2. Похоже, это тот ответ, который я ищу, но где мне реализовать этот tapGestureHandler? Как это срабатывает? Приветствия.

3. @f0rz Первый блок кода в моем вопросе настраивает распознаватель жестов касания в моем собственном классе, который является подклассом UIView. По сути, вы создаете объект UIGestureRecognizer и используете addGestureRecognizer: метод UIView, чтобы добавить его.

4. @MagicBulletDave: У меня была похожая проблема, и, используя ваше решение, я отменил жест, если внизу иерархии была кнопка UIButton, но я хотел знать, как мне разрешить моей кнопке UIButton получать событие press, которое она не получает.

5. Привет, тебе нужно убедиться, что для свойства cancelsTouchesInView твоего распознавателя жестов установлено значение NO.

Ответ №2:

В документации Apple показан ответ:

 - (void)viewDidLoad {
      [super viewDidLoad];
      // Add the delegate to the tap gesture recognizer
      self.tapGestureRecognizer.delegate = self;
}

// Implement the UIGestureRecognizerDelegate method
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:    (UITouch *)touch {
      // Determine if the touch is inside the custom subview
     if ([touch view] == self.customSubview){
         // If it is, prevent all of the delegate's gesture recognizers
         // from receiving the touch
        return NO;
     }
     return YES;
}
  

Конечно, в этом случае customSubview будет subview на странице, на которой есть кнопки (или даже кнопки на ней)

Ответ №3:

Swift 3

Установите UITapGestureRecognizer

 let tap = UITapGestureRecognizer(target: self, action: #selector(Class.didTap))
tap.delegate = self
  

Метод делегирования UITapGestureRecognizer:

 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return touch.view != buttonThatShouldCancelTapGesture
}
  

Ответ №4:

Вы можете создать подкласс UIView и перезаписать -touchesBegan селектор, или вы можете поиграть со opaque свойством subviews, чтобы сделать их «невидимыми» для прикосновений (если view.opaque = НЕТ, представление игнорирует события касания).

Комментарии:

1. Привет, Рубен, спасибо за предложения. Я не совсем уверен, что они помогут в этом случае. По сути, я хочу перехватить нажатие кнопки в subView, а затем отменить касания в SuperView. UIGestureRecognizer получит все касания первым, насколько я понимаю, и я не уверен, использует ли UIButton распознаватель жестов или домашние штрихи для выполнения своих функций.

2. Хорошо, я решил аналогичную ситуацию, добавив распознаватель жестов с длительным нажатием в вид сверху: когда пользователь долго нажимает на страницу, он получает доступ к подвидам (и всем кнопкам, которые вы хотите там иметь). Используйте UILongPressGestureRecognizer

3. Приветствую Рубена, попробую и дам вам знать, как у меня дела.

4. Привет, Рубен, извини, я просто не мог заставить это работать, и мне казалось, что я добавляю все больше и больше кода. Я придумал решение (см. Мой ответ) и пока не приму это, пока не получу некоторую обратную связь относительно его обоснованности. Спасибо за всю помощь, Дэйв.

5. Своим последним ответом я хотел предложить решение, которое, вероятно, не соответствует вашим требованиям. Я хотел сказать, что вы могли бы поместить UILongPressGestureRecognizer в верхний вид, который при обнаружении анимировал бы исчезновение этого вида и позволял пользователю касаться всех кнопок внизу. Это не то, что вам действительно было нужно! Извините за неудобства