UIView - “父级用户互动已启用”为false,但对于儿童为真?

时间:2011-05-04 17:18:36

标签: cocoa-touch ios uiview

父视图上的userInteractionEnabled = NO似乎会阻止用户在所有子视图上进行交互。它是否正确?有没有办法解决这个问题?

6 个答案:

答案 0 :(得分:35)

这是正确的,父视图上的userInteractionEnabled设置为NO将向下级联到所有子视图。如果您需要某些子视图以启用交互,而不启用其他子视图,则可以将子视图分成两个父视图:一个使用userInteractionEnabled = YES,另一个使用NO。然后将这两个父视图放在主视图中。

答案 1 :(得分:15)

您可以将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的子视图!但在我的情况下它运作良好。

更好的解决方案可能是提到的那个 Disable touches on UIView background so that buttons on lower views are clickable提到使用-pointInside:withEvent:;与之前的解决方案相比,它更好的方式是您不需要指定'_backView'来接收事件(事件只是传递给链中的下一个视图)!缺点可能是我们需要对所有子视图执行-pointInside:withEvent:(虽然可能忽略了开销)

答案 2 :(得分:2)

我刚遇到一个奇怪的情况。我有一个UIView(称之为V),它有一个UIButton作为子视图。调用此UIButton,按钮X.下面是我用于按钮X的目标/选择器的方法。下面的自身是视图V.发送者参数是按钮X.

导致我出现问题的情况是,如果我触摸我的UI上的另一个按钮(在导航栏上,调用此按钮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

也就是说,按钮动作发生了,按钮的超级视图禁用了用户交互!子视图仍然启用了用户交互!!

对于那些认为这看似虚假的人,在我的应用程序的UI上,在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>
}

答案 3 :(得分:0)

我在xib中这样做,这是我的“自定义警报控制器”-view。

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

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

答案 4 :(得分:0)

为此,我提出了一个怪异的解决方案,在tableView单元格中有一个子视图,我希望该子视图是可触摸的,但父级视图不应该...

以上两种解决方案都不适合我,但我找到了另一种解决方案。 转到情节提要,然后将tapGestureRecognizer添加到父视图以吸收父视图上的触摸。 问题解决了!

答案 5 :(得分:0)

这是解决方案 创建从“ UIView”继承的类,并编写覆盖“内部点”的func

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中,超级视图必须使用此类