UIView - "взаимодействие с пользователем включено" ложно для родителя, но верно для потомка? - PullRequest
55 голосов
/ 04 мая 2011

Похоже, что userInteractionEnabled = NO в родительском представлении предотвратит взаимодействие с пользователем во всех подпредставлениях. Это правильно? Есть ли способ обойти это?

Ответы [ 5 ]

35 голосов
/ 04 мая 2011

Это верно, userInteractionEnabled, установленный на NO в родительском представлении, будет каскадно переходить ко всем подпредставлениям.Если вам нужно, чтобы некоторые подпредставления включили взаимодействие, но не другие, вы можете разделить ваши подпредставления на два родительских представления: одно с userInteractionEnabled = YES, а другое NO.Затем поместите эти два родительских представления в главное представление.

15 голосов
/ 30 ноября 2011

Вы можете создать подкласс 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: на всех подпредставлениях (хотя может иметь незначительные накладные расходы)

2 голосов
/ 20 декабря 2014

Я просто наткнулся на странную ситуацию. У меня есть UIView (назовите это, V), который имеет UIButton в качестве подпредставления. Назовите эту кнопку UIB, кнопка X. Ниже приведен метод, который я использую для цели / селектора кнопки X. Ниже self - это представление V. Параметр отправителя - кнопка X.

Ситуация, которая вызывает у меня проблему, заключается в том, что если я коснусь другой кнопки в моем пользовательском интерфейсе (на панели навигации, нажмите эту кнопку Y), а затем очень быстро коснитесь кнопки X, где действие кнопки Y отключает вид V, I по-прежнему получать сенсорное событие, отправленное на кнопку 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>
}
0 голосов
/ 22 апреля 2019

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

Ни одно из перечисленных выше решений не помогло мне, но я нашел другое решение.Перейдите к раскадровке и добавьте tapGestureRecognizer в родительское представление, чтобы поглощать прикосновения к родительскому представлению.Проблема решена!

0 голосов
/ 09 января 2018

Я делаю это в xib, который является моим "настраиваемым контроллером оповещений".

for (UIView *subview in self.superview.subviews) {

    if (![subview isEqual:self]) {
        subview.userInteractionEnabled = NO;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...