Как надежно найти правильный вид для UIGestureRecognizer? - PullRequest
17 голосов
/ 15 июня 2011

У меня есть куча UIViews, как на картинке ниже.Красный / розовый (полупрозрачный) вид сверху других.

  • Красный имеет UISwipeGestureRecognizer.
  • Зеленый имеет UITapGestureRecognizer.
  • Синий не имеет распознавателя.

enter image description here

Нажмите на видимая (нижняя левая) часть зеленого вызывает его распознаватель.

касание скрытых частей зеленого не вызывает его распознаватель (красные блокиЭто).

Вот в чем проблема: я хочу, чтобы Грин сработал.Как я могу это сделать?

На практике представления могут быть в любом порядке, в любом количестве и быть подпредставлениями друг друга и т. Д. Но проблема та же:

Какмогу ли я надежно найти самый верхний вид, который может обрабатывать жест (касание или пролистывание)?


Я пробовал с кодом ниже.Он аккуратно пересекает все виды, но терпит неудачу, так как не может знать, является ли событие частью пролистывания или касания.Таким образом, метод всегда возвращает красный вид.Если я удаляю свайп-распознаватель из красного, код работает правильно.

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{
    UIView *hitView = [super hitTest:point withEvent:event];
    if (hitView == self)
    {
        if (self.hasASwipeRecognizer)
            return self;  // What if this was a tap?
        if (self.hasATapRecognizer)
            return self; 
        else
            return nil;
    }
    else
         return hitView;
 }

Ответы [ 3 ]

17 голосов
/ 27 июня 2011

Альтернативой добавлению распознавателя жестов в эти представления может быть добавление распознавателей жестов в родительское представление и надлежащим образом обрабатывать сценарии использования с использованием метода делегата gestureRecognizer:shouldReceiveTouch:.

Укажите, должен ли конкретный распознаватель получить касание и вернуть YES.Например, если переданный распознаватель жестов является распознавателем пролистывания, проверьте, находится ли точка касания в зеленом виде, и верните YES.Возврат NO в противном случае.

Если существуют похожие распознаватели жестов, я предлагаю сохранить ссылку и проверить ее.

Использование

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint pointInView = [touch locationInView:gestureRecognizer.view];

    if ( [gestureRecognizer isMemberOfClass:[UITapGestureRecognizer class]] 
        && CGRectContainsPoint(self.blueView.frame, pointInView) ) {
        return YES;
    } 

    if ( [gestureRecognizer isMemberOfClass:[UISwipeGestureRecognizer class]] 
        && CGRectContainsPoint(self.greenView.frame, pointInView) ) {
        return YES;
    }

    return NO;
}
3 голосов
/ 21 января 2014

Мои решения:

-(void)handleGesture:(UIGestureRecognizer*)gestureRecognizer {
    CGPoint touchPoint = [tapGestureRecognizer locationInView:viewUnderTest];
    if ([viewUnderTest pointInside:touchPoint withEvent:nil]) {
        NSLog(@"Hit done in view under test");
    }
}
3 голосов
/ 15 июня 2011

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

...