UIView - "взаимодействие с пользователем включено" ложно для родителя, но верно для потомка?
Похоже, что userInteractionEnabled=NO в родительском представлении предотвратит взаимодействие с пользователем во всех подпредставлениях. Это правильно? Есть ли способ обойти это?
4 ответа
Это верно, userInteractionEnabled, установленный в NO в родительском представлении, будет каскадно переходить ко всем подпредставлениям. Если вам нужно, чтобы некоторые подпредставления включили взаимодействие, но не другие, вы можете разделить ваши подпредставления на два родительских представления: одно с userInteractionEnabled = YES, а другое NO. Затем поместите эти два родительских представления в основной вид.
Вы можете создать подкласс UIView и переопределить hitTest:withEvent: таким образом, чтобы передать сенсорные события в указанное вами представление (_backView):
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if (view == self) {
view = _backView;
}
return view;
}
Если событие касания должно было обрабатываться этим представлением, оно будет передано "_backView" (это может быть IBOutlet, чтобы его можно было установить с помощью построителя интерфейса); и если это должно было быть обработано любым дочерним представлением, просто верните этого потомка (результат [super hitTest:point withEvent:event]
;)
Это решение подходит для тех случаев, когда вы знаете, в какое представление нужно передавать события; кроме того, не знаю, есть ли у него проблемы, так как мы возвращаем представление (_backView), которое не является подпредставлением текущего UIView!! но это работало нормально в моем случае.
Лучшим решением может быть упомянутое в разделе "Отключить касания на фоне UIView", чтобы кнопки на нижних представлениях можно было нажимать. -pointInside:withEvent:
; по сравнению с предыдущим решением лучше, если вам не нужно указывать _backView для получения событий (событие просто передается следующему представлению в цепочке)! недостатком может быть то, что нам нужно выполнить -pointInside:withEvent:
на всех подпредставлениях (хотя может иметь незначительные накладные расходы)
Вот решение. Создайте класс, унаследованный от "UIView", и напишите функцию, которая переопределяет "внутреннюю точку"
class TTSView: UIView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
for view in self.subviews {
if view.isUserInteractionEnabled, view.point(inside: self.convert(point, to: view), with: event) {
return true
}
}
return false
}
}
затем в раскадровке или xib супервизор должен использовать этот класс
Я сделал странное решение для этого, у меня было дочернее представление в ячейке tableView, которое я хотел быть сенсорным, но у родителя не должно быть...
Ни одно из вышеуказанных решений не помогло мне, но я нашел другое решение. Перейдите к раскадровке и добавьте tapGestureRecognizer в родительское представление, чтобы поглощать прикосновения к родительскому представлению. Задача решена!
Я просто наткнулся на странную ситуацию. У меня есть UIView (назовите это, V), который имеет UIButton в качестве подпредставления. Назовите эту кнопку UIB, кнопка X. Ниже приведен метод, который я использую для цели / селектора кнопки X. Самым ниже является представление V. Параметр отправителя - кнопка X.
Ситуация, которая вызывает у меня проблему, заключается в том, что если я коснусь другой кнопки в моем пользовательском интерфейсе (на панели навигации, назовите эту кнопку Y), а затем очень быстро коснитесь кнопки X, где действие кнопки Y отключает вид V, я все равно получаю сенсорное событие отправлено на кнопку X.
- (void) buttonAction: (UIButton *) sender
{
NSLog(@"superview: %d", sender.superview.userInteractionEnabled);
NSLog(@"button itself: %d", sender.userInteractionEnabled);
// <snip>
}
Вот вывод:
2014-12-19 16: 57: 53.826 MyApp [6161: 960615] superview: 0
2014-12-19 16: 57: 53.826 MyApp [6161: 960615] сама кнопка: 1
То есть, действие кнопки произошло, а в суперпредставлении кнопки было отключено взаимодействие с пользователем! И в подвиде все еще было включено взаимодействие с пользователем!!
Для тех из вас, кто думает, что это выглядит искусственно, в пользовательском интерфейсе моего приложения, работающем на iPad (под управлением iOS 8.1.2), это произошло случайно при моем использовании приложения. Это было не то, что я изначально пытался создать.
Мысли?
Мой текущий обходной путь приведен ниже, но кажется странным, что это необходимо!
- (void) buttonAction: (id) sender
{
NSLog(@"superview: %d", sender.superview.userInteractionEnabled);
NSLog(@"button itself: %d", sender.userInteractionEnabled);
if (! self.userInteractionEnabled) return;
// <snip>
}
Я делаю это в xib, который является моим "настраиваемым контроллером оповещений".
for (UIView *subview in self.superview.subviews) {
if (![subview isEqual:self]) {
subview.userInteractionEnabled = NO;
}
}