2012-04-21 51 views
0

我有一个子屏幕图像的网格显示在屏幕上;它基本上是以棋盘方式放置在屏幕上的一系列图像。我只是想为这些图像子视图中的每一个添加手势识别器,以便当用户触摸其中一个图像子视图时,我可以检索子视图,即坐标,标签等。我的视图层次结构如下所示:如何将手势识别器添加到一系列子视图?

  1. 超级视图
  2. 一个gridContainer视图
  3. 和每个个体子视图 - 与图像

看着苹果文档后,它好像我应该能够手势识别添加到gridContainer视图和每个子视图 - 与im年龄 - 应该继承手势识别器。到目前为止,这是我尝试过的:我已经在getter中分配了初始化网格容器视图。另外,在getter中,我调用了我的createGesture方法,该方法应该将一个手势识别器添加到gridContainer视图。但是,我在运行时收到一个错误,指向我的actionSingleTap方法。它读取EXC_BAD_EXCESS。 还值得注意的是,我不希望我的gridContainer视图以外的视图响应任何触摸事件。预先感谢您的帮助。

这里是我想要实现的代码:

- (UIView *)gridContainerView 
{ 
    if (!_gridContainerView)_gridContainerView = [[UIView alloc] init]; 
    [self createGesture]; 
    return _gridContainerView; 
} 
- (void)createGesture 
{ 
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] 
             initWithTarget:self.gridContainerView 
             action:@selector(handleSingleTap:)]; 
    singleTap.numberOfTapsRequired = 1; 

    [self.gridContainerView addGestureRecognizer:singleTap]; 
} 

如果您需要看到任何额外的代码,这是有道理的,请让我知道。

编辑:包括handleSingleTap方法:

- (IBAction)handleSingleTap:(id)sender 
{ 
    CGPoint tapPoint = [sender locationInView:sender]; 
    NSLog(@"sender = %@",sender); 
    NSLog(@"tappoint = %@", tapPoint); 
} 

回答

4

要初始化您gridContainerView普通UIView。然后你附加一个手势识别器(使用该视图实例作为目标)。然而,一个普通的UIView不执行handleSingleTap:,因此你会得到一个异常。

您应该创建一个(自定义UIView派生的)类,实现您需要该触发手势的选择器。

+0

所以我应该创建一个自定义类,它是UIView的子视图?我是否应该将我的gridContainerView放入此自定义类中,然后在我需要访问时在控制器中调用它? – Scott 2012-04-21 13:29:41

+0

不是子视图,而是子类。 – Till 2012-04-21 14:43:21

0

几个问题马上蝙蝠(甚至没有处理您的手势处理)。

您每次访问gridContainerView时都会调用createGesture。您可能只希望在创建视图时发生这种情况。此外,如果你看看createGesture,它回调到gridContainerView,其回调到createGesture,其回调到gridContainerView等

你可能想要更多的东西一样......

- (UIView *)gridContainerView 
{ 
    if (!_gridContainerView) { 
     _gridContainerView = [[UIView alloc] init]; 
     [self createGesture]; 
    } 
    return _gridContainerView; 
} 

接下来,您正尝试在视图上调用handleSingleTap。你可能希望它在控制器上:initWithTarget:self。

- (void)createGesture 
{ 
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] 
             initWithTarget:self 
             action:@selector(handleSingleTap:)]; 
    singleTap.numberOfTapsRequired = 1; 

    [self.gridContainerView addGestureRecognizer:singleTap]; 
} 

你可能想重新考虑拥有两个直接相互引用的独立方法的智慧。但是,至少在我们对访问者做出的改变之后,它应该是可以的。只要知道,如果在访问器中添加更多代码,则必须在调用createGesture之前完全设置该视图。

+0

这些都是一些好点,但我的handleSingleTap方法似乎并没有对触摸事件做出响应。我编辑了上面的代码,并包含句柄单击方法。任何想法为什么它没有响应? – Scott 2012-04-21 13:43:59

0

一些事情。首先,你将gridContainerView实例化为一个标准的UIView,然后发送消息:handleSingleTap:,它肯定不会响应。如果你想让你的gridContainerView响应消息,你需要继承UIView的子类,创建适当的方法,并将你的gridContainerView实例化为子类。其次,就整体方法而言,我将为gridContainerView创建子类(甚至可以称之为),并创建处理该手势的方法。在该方法中,您可以使用UIGestureRecognizer方法locationInView:访问被触摸/点击的点。使用这一点来确定在gridContainerView中哪个子视图被点击并执行相应的操作。要发现哪个子视图被点击,您可以遍历子视图并检查每个子视图以确定哪个包含点击的点。有几种方法的UIView有你可以用它来做到这一点:

pointInside:withEvent: hitTest:withEvent:

注意,您可以通过nil的事件。以上两件事情略有不同。如果您只是测试点是否位于视图中,请使用pointInside:withEvent,因为它将返回BOOL。方法hitTest:withEvent将导致视图搜索其所有子视图,并返回其自身或其子视图之一(如果该点在其界限之外,则返回nil)。 hitTest:withEvent可能会稍微多一点处理器密集度。此外,您也可以使用CGRectContainsPoint()进行测试。