如何只让单击手势响应同时让后面的物体响应双击?

时间:2012-07-16 23:55:56

标签: ios uiwebview uikit uigesturerecognizer ios5

我在UIWebView中显示文档。我想在文档上放置一个热点以在触发时触发操作,但我还想保持默认的UIWebView在双击时自动缩放文档的行为。在让UIWebView响应双击时,我无法弄清楚如何响应单击。

我首先将热点设置为带有动作的透明UIButton,但是双击热点导致热点动作被调用两次。所以我从按钮中移除了操作并附加了单击手势:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction:)];
singleTap.numberOfTapsRequired = 1;
singleTap.delegate = self;
[self.hotspot addGestureRecognizer:singleTap];
[singleTap release];

这与普通按钮操作相同。但后来我创建了一个双击手势,并将其配置为使用requireGestureRecognizerToFail阻止单击手势:

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zoomWebView:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.delegate = self;
[self.hotspot addGestureRecognizer:doubleTap];
[doubleTap release];

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction:)];
singleTap.numberOfTapsRequired = 1;
[singleTap requireGestureRecognizerToFail:doubleTap];
singleTap.delegate = self;
[self.hotspot addGestureRecognizer:singleTap];
[singleTap release];

- (void)zoomWebView:(UITapGestureRecognizer *)gesture {
    NSLog(@"double tap");
}

使用此设置,单击热点调用singleTapAction,双击热点调用zoomWebView(自定义方法)。这很好,因为singleTapAction不再被调用两次,但是因为UIWebView不再响应双击而不好。

我尝试通过继承UITapGestureRecognizer,将双击事件从我的doubleTap手势转发到UIWebView,重写touchesBegan和touchesEnded方法,并将其参数发送到UIWebView的相应方法。当我这样做时,我可以看到我的子类正在接收事件,但UIWebView没有响应转发的事件。这是预期的,因为Event Handling Guide for iOS表示我们只能将事件转发到UIView的自定义子类,而不是UIKit框架对象。

有没有办法阻止我的单击手势响应不会转移双击事件的双击?这似乎是一个基本要求,但我看不到一种直接的方法。我阅读并尝试了UIGestureRecognizer的touch delivery properties,但没有值的组合阻止单击手势消耗双击手势。

顺便说一下,我的视图层次结构中热点和UIWebView之间的关系是“堂兄弟” - 它们是两个兄弟视图的子视图。如果我将手势识别器添加到热点视图,Web视图或其“祖父母”视图中,我会得到相同的结果。

2 个答案:

答案 0 :(得分:15)

好的,我找到了两个部分的解决方案:

1)我必须将我的手势添加到UIWebView的父视图中。正如我想象的那样,无与伦比的事件不会在层与层的视图中穿过重叠的对象。相反,它们通过从子级到父级的视图层次结构。所以只要我将我的双击手势添加到兄弟姐妹或表兄弟身上就可以了。在UIWebView的视图中,它永远不会继续进行Web视图。这意味着我无法使用Interface Builder中的按钮或视图来确定多个热点区域。相反,我必须将所有单击事件重定向到一个方法,然后查看触摸位置以确定要触发的操作。

2)我不得不将gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:方法添加到我的视图控制器(我的手势代表)并返回YES。即使我在UIWebView中显示HTML,文本或图像内容,这也允许我的单击手势响应,UIWebView为这些内容类型实现了自己的手势。我从this answer学到了这一部分。

通过这些更改,我了解事件的层次结构:

  • 单击网页视图:我在网络视图的父视图中的单击手势响应;如果适用,网页视图的单击手势也会响应,因为启用了同步手势

  • 点按两次网页视图:我在网络视图的双击手势上的父视图会响应(但不做任何事情);我的单击手势没有响应,因为它被配置为仅在双击失败时才响应; Web视图的双击事件也会响应,因为它是视图层次结构的一部分(似乎Web视图的双击功能不使用手势,否则它将优先于我自己的手势在我原来的设置中)

通过这个解释,这里有一些工作代码:

- (void)viewDidLoad {
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapWebView:)];
    doubleTap.numberOfTapsRequired = 2;
    doubleTap.delegate = self;
    [self.webViewParent addGestureRecognizer:doubleTap];
    [doubleTap release];

    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapWebView:)];
    singleTap.numberOfTapsRequired = 1;
    [singleTap requireGestureRecognizerToFail:doubleTap];
    singleTap.delegate = self;
    [self.webViewParent addGestureRecognizer:singleTap];
    [singleTap release];
}

- (void)doubleTapWebView:(UITapGestureRecognizer *)gesture {
    NSLog(@"double-tap");
    // nothing to do here
}

- (void)singleTapWebView:(UITapGestureRecognizer *)gesture {
    NSLog(@"single-tap");
    CGPoint touchLocation = [gesture locationInView:self.webViewParent];
    float x = touchLocation.x;
    float y = touchLocation.y;
    CGRect frame = self.webViewParent.frame;
    if (y < frame.size.height * .33) {
        NSLog(@"top");
    } else if (y > frame.size.height * .67) {
        NSLog(@"bottom");
    } else if (x < frame.size.width * .33) {
        NSLog(@"left");
    } else if (x > frame.size.width * .67) {
        NSLog(@"right");
    } else {
        NSLog(@"center");
    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

答案 1 :(得分:-2)

自事件处理开始以来,鼠标点击一直存在问题。

在单击实例中,任何软件都无法确定是否会发生双击。

因此,如果您想要单击并双击,则必须进行自己的双击处理。

单击实例的时间,并生成您自己的双击事件。

希望可以转移到您的上下文中进行点击。