2013-03-17 2 views
27

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

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

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

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 на два отдельных, которые я бы предпочел избежать.

Спасибо

ответ

9

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

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

0

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

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

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


    CGPoint tapPoint = [gestureRecognizer locationInView:nil]; 

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

Это дорогостоящий и волосатый, если необходимо проверить множество подзапросов. – CodaFi

+0

yup..I смотрю .. Я не вижу никаких других хороших решений .. если у вас есть, не стесняйтесь делиться .. :) –

0

ДОБАВЛЕНО:

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

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

-(void)tapGestureHandler:(UITapGestureHandler)gesture 

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

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

Я предлагаю переопределить внутри супервизора.

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

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

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

Event handling for iOS - how hitTest:withEvent: and pointInside:withEvent: are related?

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

ИЛИ

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

+0

К сожалению, я не думаю, что это работает. Согласно документам, gesture.view дает вам «Вид, на который прикреплен распознаватель жестов». который дает весь вид контейнера, а не подпункт. Второй вариант выглядит многообещающим, я отдам его. –

+0

Отлично, я получил его, используя метод hitTest: withEvent. См. Сообщение ниже. –

11

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

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 
    } 
} 
37

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

Реализовать функцию UIGestureRecognizerDelegate, принимают только Touchs на надтаблицы, не принимают Touchs на подвидов:

- (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; 
} 
4

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

В вашем файле .h UIViewController включают этот делегат

@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; то метод делегата крана теперь стрелять на кране.

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

-(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; 
} 

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

Приветствия

2

участки ответов, добавив еще одно альтернативное решение. Инициализировать вид тега из подвидов вы не хотите получать от прикосновения как 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... 
} 

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

Смежные вопросы