2011-02-07 82 views
5

假设我有一个UIViewController子类,照顾一些UIViews。这些UIViews添加为UIViewController的view属性的子视图):UIView,其superview和touchesBegan:

的UIViewController:

- (void)viewDidLoad { 
    UIImageView *smallImageView... 
    [self.view addSubview:smallImageView]; 

    UIButton *button.. 
    [self.view addSubview:button]; 

    UIView *bigUIView.. // covers the entire screen (frame = (0.0, 0.0, 1024.0, 768.0)) 
    [self.view addSubview:bigUIView]; 
... 
} 

据我所知,因为bigUIView是最前面的视图,并覆盖整个屏幕,它将接收touchesBegan:withEvent:和其他视图如button将不会收到任何触摸事件。

在我的应用程序bigUIView必须是最顶层的视图,因为它包含主要的用户界面对象(CALayers,实际上,主要的游戏对象),当动画时,必须在所有其他辅助UI元素(UIButtons等)。但是,我希望能够在Responder Chain中保留UIButtons和其他对象。

我试图实现在bigUIView类以下内容:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
    [self.superview touchesBegan:touches withEvent:event]; 

    ... hit test the touch for this specific uiview.. 
} 

注:

  1. bigUIView的上海华指UIViewController的view财产,触摸事件它传播到它的所有子视图?
  2. bigUIView必须有userInteractionEnabled = YES,因为它也处理用户输入。
  3. 我不能将button/smallImageView放在前面,因为它会出现在主要游戏对象(子层bigUIView)的上方。

在此先感谢。

回答

11

尝试覆盖bigUIView类中的pointInside:withEvent:,如果该点位于背景视图的其他子视图之一的框架矩形内,则返回NO。由于它是这些其他视图的兄弟,所以命中测试机制将继续测试其他子视图并找到与用户所触及的点相对应的一个子视图。

阿洛斯,考虑在您的UIViewController子类中实施事件阶段方法(-touchesBegan:withEvent:等),而不是在bigUIView类中。 iOS在响应者链中的视图后面插入视图控制器,因此事件消息会向视图控制器冒泡,除非其中一个子视图(例如,按钮)拦截它。视图控制器然后可以发送你喜欢的任何消息给它的任何视图。

+0

谢谢jlehr,`pointInside:withEvent:`是解决方案。当点位于其他子视图的框架矩形内时,通过返回NO,会导致不调用bigUIView的`-touchesBegan:withEvent:`方法,并触发`button`的操作。请注意,这会导致`bigUIView`和`button`之间的耦合。当bigUIView覆盖整个屏幕时,我如何才能在`UIViewController`中拦截事件阶段方法?在`bigUIView`类中创建一个不同的方法签名,并通过“catch all”UIViewController类来委托它? – 2011-02-07 16:45:49

+1

不,不要在`bigUIView`中实现事件阶段方法。这样,消息将被转发到响应者链,直到它们到达具有重载实现的对象(例如`UIButton`或您的自定义`UIViewController`子类)。 – jlehr 2011-02-07 17:09:01

0

通常在响应者链中,事件传递给超级视图,而不是子视图。无论如何,我会将事件中的点转换为按钮的本地坐标系,如果碰撞,则向控制器发送一个动作。