iPhone/iPad - 为什么父级UIView会阻止触摸事件传递到子视图?

5

我有一个UIView,它有许多子视图。子视图应该能够接收触摸事件,但由于某种原因父UIView却接收了触摸事件并没有将其传递下去。我按照通常的方式创建了它:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0,0,1024,768)];
    self.mainView = myView;
    [myView release];

    [self.view addSubview:self.mainView];

然后我创建子视图并像平常一样添加它们:
[self.mainView addSubview:someOtherView];

我知道当我在主UIWindow中监听时,self.mainView会获取触摸事件:

VIEW: <UIView: 0x8d34aa0; frame = (0 0; 1024 768);

但是,为什么我不能让子视图接收触摸呢?有时候我真的不理解这种情况。我没有更改主视图的任何默认属性。

3个回答

15

这与父视图的框架有关。如果框架没有包含子视图,那么它们将无法接收到触摸事件。


1
在定位子视图时,请记得参考父视图的“边界”。您的框架可能是屏幕上实际位置,也可能不是。 - MOK9
@sol:你怎么知道那是这种情况? - user749127

12

如解决方案所述,如果UIView的子视图位于其父视图的边界之外,则触摸事件不会传递给子视图。

但是,如果您希望这些子视图响应触摸事件,请覆盖父视图的hitTest:withEvent:方法。

有关事件传递的文档

触摸事件。窗口对象使用命中测试和响应者链来查找接收触摸事件的视图。在命中测试中,窗口在视图层次结构的最顶部视图上调用hitTest:withEvent:方法;该方法通过递归调用视图层次结构中每个返回YES的pointInside:withEvent:方法来继续进行,直到找到包含触摸发生位置的子视图为止。那个视图成为命中测试视图。

  1. 创建一个UIView的子类(或其他UIView子类)。
  2. 覆盖hitTest:withEvent:方法。
  3. 将此UIView子类用作父视图,以便子视图可以响应触摸事件。

在子类中添加下面的方法:

(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
    UIView *iSubView;

    while ((iSubView = [reverseE nextObject])) {

        UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
        if(viewWasHit) {
            return viewWasHit;
        }

    }
    return [super hitTest:point withEvent:event];
}

注意:因为子视图是从后往前排列的,我们想要测试最前面的视图,所以使用了反向枚举器。


0
你的触摸事件处理程序是否调用了超类的处理程序?
例如,在你的touchesBegan中,调用:
[super touchesBegan:touches withEvent:event];

我没有任何触摸处理程序。子视图只是不响应触摸。例如,一个子视图上的手势识别器无法工作。 - sol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接