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