UIButton внутри представления с UITapGestureRecognizer

У меня есть вид с UITapGestureRecognizer. Поэтому, когда я нажимаю на вид, над этим представлением появляется другое представление. Это новое представление имеет три кнопки. Когда я сейчас нажимаю на одну из этих кнопок, я не получаю действие кнопок, я получаю только действие жестового нажатия. Поэтому я больше не могу использовать эти кнопки. Что я могу сделать, чтобы передать события этим кнопкам? Странно, что кнопки все еще выделяются.

Я не могу просто удалить UITapGestureRecognizer после того, как получил его. Потому что с ним можно также удалить новый вид. Значит, я хочу поведение , такое как элементы управления в полноэкранном режиме.

Ответ 1

Вы можете установить ваш контроллер или просмотр (в зависимости от того, какой из них распознает распознавание жестов) в качестве делегата UITapGestureRecognizer. Затем в делегате вы можете реализовать -gestureRecognizer:shouldReceiveTouch:. В своей реализации вы можете проверить, принадлежит ли прикосновение к вашему новому подзону, и если это так, попросите распознавателя жестов игнорировать его. Что-то вроде следующего:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    // test if our control subview is on-screen
    if (self.controlSubview.superview != nil) {
        if ([touch.view isDescendantOfView:self.controlSubview]) {
            // we touched our control surface
            return NO; // ignore the touch
        }
    }
    return YES; // handle the touch
}

Ответ 2

В качестве продолжения Кейси последует ответ Кевина Балларда:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
        if ([touch.view isKindOfClass:[UIControl class]]) {
            // we touched a button, slider, or other UIControl
            return NO; // ignore the touch
        }
    return YES; // handle the touch
}

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

Ответ 3

Нашел ответ здесь: ссылка

Вы также можете использовать

tapRecognizer.cancelsTouchesInView = NO;

Что мешает распознавателю крана быть единственным, чтобы поймать все крана

ОБНОВЛЕНИЕ - Майкл упомянул ссылку на документацию, описывающую это свойство: cancellsTouchesInView

Ответ 4

Как ответ на вопрос Кевина Балларда, у меня была такая же проблема, и я использовал этот код:

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

Он имеет такой же эффект, но это будет работать на любом UIButton на любой глубине представления (мой UIButton был несколько видов в глубину, и делегат UIGestureRecognizer не имел ссылки на него.)

Ответ 5

В iOS 6.0 и более поздних версиях действия по умолчанию предотвращают совпадение поведения распознавателя жестов. Например, действие по умолчанию для кнопки - однократное нажатие. Если у вас есть один распознаватель жестов при нажатии на родительский вид кнопок, и пользователь нажимает кнопку, тогда метод действия кнопок получает событие касания вместо распознавателя жестов. Это относится только к распознаванию жестов, которое перекрывает действие по умолчанию для элемента управления, которое включает в себя:.....

Из документа API Apple API

Ответ 6

Эти ответы были неполными. Мне пришлось читать несколько сообщений о том, как использовать эту логическую операцию.

В вашем *.h файле добавьте это

@interface v1ViewController : UIViewController <UIGestureRecognizerDelegate>

В вашем *.m файле добавьте этот

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

    NSLog(@"went here ...");

    if ([touch.view isKindOfClass:[UIControl class]])
    {
        // we touched a button, slider, or other UIControl
        return NO; // ignore the touch
    }
    return YES; // handle the touch
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.



    //tap gestrure
    UITapGestureRecognizer *tapGestRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenTappedOnce)];
    [tapGestRecog setNumberOfTapsRequired:1];
    [self.view addGestureRecognizer:tapGestRecog];


// This line is very important. if You don't add it then your boolean operation will never get called
tapGestRecog.delegate = self;

}


-(IBAction) screenTappedOnce
{
    NSLog(@"screenTappedOnce ...");

}

Ответ 7

Найден другой способ сделать это из здесь. Он обнаруживает касание внутри каждой кнопки или нет.

(1) pointInside: withEvent: (2) locationInView:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
       shouldReceiveTouch:(UITouch *)touch {
    // Don't recognize taps in the buttons
    return (![self.button1 pointInside:[touch locationInView:self.button1] withEvent:nil] &&
            ![self.button2 pointInside:[touch locationInView:self.button2] withEvent:nil] &&
            ![self.button3 pointInside:[touch locationInView:self.button3] withEvent:nil]);
}

Ответ 8

Вот Swift-версия ответа Лили Баллард, которая сработала для меня:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if (scrollView.superview != nil) {
        if ((touch.view?.isDescendantOfView(scrollView)) != nil) { return false }
    }
    return true
}

Ответ 9

Вы можете остановить UITapGestureRecognizer от отмены других событий (например, нажатия на вашу кнопку), установив следующие логические значения:

    [tapRecognizer setCancelsTouchesInView:NO];

Ответ 10

Если ваш сценарий выглядит следующим образом:

У вас есть простой вид, а некоторые элементы UIButtons, UITextField добавлены в виде представлений для этого представления. Теперь вы хотите убрать клавиатуру, когда вы касаетесь где-либо еще в представлении, кроме элементов управления (добавленные надстройки)

Тогда решение:

Добавьте следующий метод к вашему XYZViewController.m(который имеет ваше представление)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}

Ответ 11

Оптимизируя ответ cdasher, вы получаете

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