Подтвердить что ты не робот

Исключить подпункты из UIGestureRecognizer

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

В настоящий момент прикосновение в любом месте контейнера, в том числе внутри подзонов, активирует распознаватель жестов.

Реализация выглядит примерно так: В контроллере:

ContainerView *containerView = [[ContainerView alloc] initWithSubViews:array];
UITapGestureRecognizer *tap = [UITapGestureRecognizer alloc] initWithTarget:self action:@selector(someSelector)];
[containerView addGestureRecognizer:tap];
[self.view addSubView:containerView];

В ContainerView.m

-(id)initWithSubviews:(NSArray *)array {
    for (subView *s in array) {
        [self addSubView:s];
    }
    return self;
}

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

Спасибо

4b9b3361

Ответ 1

iOS 6 представляет новую новую функцию, которая решает эту точную проблему - UIView (subview) может возвращать NO из gestureRecognizerShouldBegin: (распознаватель жестов, прикрепленный к супервину). Действительно, это значение по умолчанию для некоторых подклассов UIView в отношении некоторых распознавателей жестов уже (например, UIButton относительно UITapGestureRecognizer, прикрепленного к супервину).

Смотрите мою книгу по этой теме: http://www.apeth.com/iOSBook/ch18.html#_gesture_recognizers

Ответ 2

Я использовал простой способ ниже. Он работает правильно!

Реализовать функцию UIGestureRecognizerDelegate, принимать только прикосновения к супервизу, не принимать прикосновения к subviews:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (touch.view != _mySuperView) { // accept only touchs on superview, not accept touchs on subviews
        return NO;
    }

    return YES;
}

Ответ 3

Мне удалось заставить его работать, выполнив следующие действия:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureHandler:)];

// ...

-(void) tapGestureHandler:(UITapGestureRecognizer *)sender {
    CGPoint point = [sender locationInView:sender.view];
    UIView *viewTouched = [sender.view hitTest:point withEvent:nil];
    if ([viewTouched isKindOfClass:[ThingIDontWantTouched class]]) {
        // Do nothing;
    } else {
        // respond to touch action
    }
}

Ответ 4

Не забудьте добавить и установить метод делегата -

В ваш UIViewController.h файл входит этот делегат

@interface YourViewController: UIViewController<UIGestureRecogniserDelegate>

Затем, когда вы создаете свой объект tapGesture (например, в viewDidLoad)

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(actionMethodYouWantToHappenOnTap)];  

    tap.delegate = self;  //Remember to set delegate! Otherwise the delegate method won't get called.

    [self.view addGestureRecognizer:tap];

Помня о том, чтобы установить метод делегирования tap.delegate = self;, затем будет отключен метод делегата для подключения.

В этом методе вы обрабатываете, когда хотите использовать распознавание жеста tap, в моем коде я хотел, чтобы он игнорировал ответвление, если было видно какое-то подвью

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{

     if (!mySubview.hidden){
     return NO;   //This fired if said subview was visible, though whatever the condition of where and when you want tap to work, can be handled within this delegate method.
     }

    return YES;
}

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

Приветствия

Ответ 5

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

- (void)viewDidLoad {
    [super viewDidLoad];
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    tap.delegate = self;
    [self.view addGestureRecognizer:tap];
}

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (touch.view.tag == 1) {
        return NO;
    }
    return YES;
}

-(void)handleTap:(id)sender
{
//Handle tap...
}

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

Ответ 6

Если вы добавили UITapGestureRecognizer для ContainerView, он должен ответить со всем ContainerView. Он не будет возражать против его подсмотров.

Проверьте местоположение Жест, если оно находится в позиции вашего просмотра, просто пропустите действия жестов.

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


    CGPoint tapPoint = [gestureRecognizer locationInView:nil]; 

   //check your tapPoint contains ur subview frame, skip.else do ur actions
}

Ответ 7

ДОБАВЛЕН:

Я просто подумал о чем-то лучшем.

в вашем обработчике

-(void)tapGestureHandler:(UITapGestureHandler)gesture

проверьте, является ли gesture.view супервидом. он будет возвращать subviews, если subviews будут прослушиваться.

=============================================== =====

Я бы предложил переопределить внутри супервизора.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

это вызывается, чтобы определить, попадает ли жест в представление

см. ответ на этот вопрос, чтобы посмотреть, как он работает по умолчанию.

Обработка событий для iOS - как hitTest: withEvent: и pointInside: withEvent: связаны?

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

ИЛИ

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