UIView - "взаимодействие с пользователем включено" false для родителя, но верно для ребенка?

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

Ответ 1

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

Ответ 2

Вы можете создать подкласс 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, чтобы кнопки на нижних окнах можно было нажимать. по сравнению с предыдущим решением лучше, если вам не нужно указывать _backView для получения событий (событие просто передается следующему представлению в цепочке)! недостаток может заключаться в том, что нам нужно выполнить -pointInside:withEvent: для всех подпредставлений (хотя может иметь незначительные накладные расходы)

Ответ 3

Я просто столкнулся с странной ситуацией. У меня есть UIView (назовите это, V), который имеет UIButton как subview. Вызовите этот UIButton, кнопку 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] superiew: 0
2014-12-19 16: 57: 53.826 MyApp [6161: 960615] сама кнопка: 1

То есть, действие кнопки произошло, и у кнопки superview было отключено взаимодействие с пользователем! И в подвью все еще было включено взаимодействие с пользователем!!

Для тех из вас, кто думает, что это кажется искусственным, в моем пользовательском интерфейсе приложения, работающем на 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>
}

Ответ 4

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

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

    if (![subview isEqual:self]) {
        subview.userInteractionEnabled = NO;
    }
}

Ответ 5

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

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