Я пытаюсь понять, как это сделать правильно . Я попытался изобразить ситуацию:
Я добавляю UITableView
как подвид UIView
. Объект UIView
реагирует на касание и pinchGestureRecognizer
, но при этом tableview перестает реагировать на эти два жеста (он по-прежнему реагирует на смахивания).
Я заставил его работать с помощью следующего кода, но это явно не лучшее решение, и я уверен, что есть способ лучше. Это помещено в UIView
(супервизор):
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if([super hitTest:point withEvent:event] == self) {
for (id gesture in self.gestureRecognizers) {
[gesture setEnabled:YES];
}
return self;
}
for (id gesture in self.gestureRecognizers) {
[gesture setEnabled:NO];
}
return [self.subviews lastObject];
}
objective-c
ios
uiview
uigesturerecognizer
uiresponder
Andershqst
источник
источник
hitTest:withEvent:
илиpointInside:withEvent:
.return !(touch.view == givenView);
если вы просто хотите исключить данное представление илиreturn !(touch.view.tag == kTagNumReservedForExcludingViews);
когда вы хотите, чтобы ваш распознаватель не обрабатывал касание для целой группы различных подвидов.- (BOOL)isDescendantOfView:(UIView *)view
. Это также отлично работает- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
при создании подкласса UIGestureRecognizer.Блокировка событий касания для подпредставлений - поведение по умолчанию. Вы можете изменить это поведение:
UITapGestureRecognizer *r = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(agentPickerTapped:)]; r.cancelsTouchesInView = NO; [agentPicker addGestureRecognizer:r];
источник
translationInView
метод. Таким образом, реализация упомянутого выше метода UIGestureRecognizerDelegate приведет только к сбою с ошибкой... unrecognized selector sent to blah
. Для того, чтобы проверить, использовать что - то вроде:CGRectContainsPoint(subview.bounds, [recognizer locationInView:subview])
.Я отображал выпадающее подвид, у которого было собственное табличное представление. В результате
touch.view
иногда возвращались такие классы, какUITableViewCell
. Мне пришлось пройти через суперклассы, чтобы убедиться, что это подкласс, который, как я думал, был:-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { UIView *view = touch.view; while (view.class != UIView.class) { // Check if superclass is of type dropdown if (view.class == dropDown.class) { // dropDown is an ivar; replace with your own NSLog(@"Is of type dropdown; returning NO"); return NO; } else { view = view.superview; } } return YES; }
источник
Опираясь на @Pin Ши Ван ответ . Мы игнорируем все касания, кроме тех, которые находятся в представлении, содержащем распознаватель жестов касания. Все нажатия перенаправляются в иерархию представлений как обычно, как мы установили
tapGestureRecognizer.cancelsTouchesInView = false
. Вот код в Swift3 / 4:func ensureBackgroundTapDismissesKeyboard() { let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap)) tapGestureRecognizer.cancelsTouchesInView = false self.view.addGestureRecognizer(tapGestureRecognizer) } @objc func handleTap(recognizer: UIGestureRecognizer) { let location = recognizer.location(in: self.view) let hitTestView = self.view.hitTest(location, with: UIEvent()) if hitTestView?.gestureRecognizers?.contains(recognizer) == .some(true) { // I dismiss the keyboard on a tap on the scroll view // REPLACE with own logic self.view.endEditing(true) } }
источник
UISwipeActionStandardButton
? Я пробовал с.some(UISwipeActionStandardButton)
Одна из возможностей - создать подкласс вашего распознавателя жестов (если вы еще этого не сделали) и переопределить
-touchesBegan:withEvent:
таким образом, чтобы он определял, начинается ли каждое касание в исключенном подвиде, и вызывает-ignoreTouch:forEvent:
это касание, если оно началось .Очевидно, вам также необходимо добавить свойство для отслеживания исключенных подвидов или, что лучше, массива исключенных подвидов.
источник
Можно обойтись без наследования какого-либо класса.
вы можете проверить gestureRecognizers в селекторе обратного вызова жеста
если view.gestureRecognizers не содержит вашего gestureRecognizer, просто проигнорируйте его
например
- (void)viewDidLoad { UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; singleTapGesture.numberOfTapsRequired = 1; }
проверьте view.gestureRecognizers здесь
- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer { UIEvent *event = [[UIEvent alloc] init]; CGPoint location = [gestureRecognizer locationInView:self.view]; //check actually view you hit via hitTest UIView *view = [self.view hitTest:location withEvent:event]; if ([view.gestureRecognizers containsObject:gestureRecognizer]) { //your UIView //do something } else { //your UITableView or some thing else... //ignore } }
источник
singleTapGesture.cancelsTouchesInView = NO;
добавлено кviewDidLoad
вышеЯ создал подкласс UIGestureRecognizer, предназначенный для блокировки всех распознавателей жестов, прикрепленных к супервизорам определенного представления.
Это часть моего проекта WEPopover. Вы можете найти это здесь .
источник
реализовать делегат для всех распознавателей parentView и поместить метод gestureRecognizer в делегат, который отвечает за одновременный запуск распознавателей:
func gestureRecognizer(UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer:UIGestureRecognizer) -> Bool { if (otherGestureRecognizer.view.isDescendantOfView(gestureRecognizer.view)) { return true } else { return false }
}
Вы можете использовать методы отказа, если хотите, чтобы запускались дочерние элементы, но не родительские распознаватели:
https://developer.apple.com/reference/uikit/uigesturerecognizerdelegate
источник
Я тоже делал поповер, и вот как я это сделал
func didTap(sender: UITapGestureRecognizer) { let tapLocation = sender.locationInView(tableView) if let _ = tableView.indexPathForRowAtPoint(tapLocation) { sender.cancelsTouchesInView = false } else { delegate?.menuDimissed() } }
источник
Вы можете выключить и включить ... в моем коде я сделал что-то вроде этого, так как мне нужно было выключить его, когда клавиатура не отображалась, вы можете применить это к своей ситуации:
назовите это viewdidload и т. д.:
NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(notifyShowKeyboard:) name:UIKeyboardDidShowNotification object:nil]; [center addObserver:self selector:@selector(notifyHideKeyboard:) name:UIKeyboardWillHideNotification object:nil];
затем создайте два метода:
-(void) notifyShowKeyboard:(NSNotification *)inNotification { tap.enabled=true; // turn the gesture on } -(void) notifyHideKeyboard:(NSNotification *)inNotification { tap.enabled=false; //turn the gesture off so it wont consume the touch event }
Это отключает кран. Однако мне пришлось превратить tap в переменную экземпляра и отпустить ее в dealloc.
источник