2012-07-16 25 views
5

我在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,覆盖touchesBegan和touchesEnded方法,并将它们的参数发送到UIWebView的相应方法,将我的doubleTap手势的双击事件转发到UIWebView。当我这样做时,我可以看到我的子类正在接收事件,但UIWebView没有响应转发的事件。这是可以预料的,因为Event Handling Guide for iOS表示我们只能将事件转发给UIView的自定义子类,而不是UIKit框架对象。

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

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

+0

不知道这(因此它是一个注释),但你不能添加一个水龙头手势UIWebView? – 2012-07-17 00:01:20

+0

@DeanPucsek我这样做了一段时间,它显示PDF文档时工作。但是,如果UIWebView中显示的内容是HTML或JPG,则UIWebView将捕获其自身操作的单击,并且UIGestureRecognizer不会收到该事件。用热点视图处理这个会更方便,但是如果我可以使它适用于所有的UIWebView内容类型,我可以回到这种方法。 – arlomedia 2012-07-17 04:28:27

回答

15

好吧,我发现了一个解决方案分为两个部分:

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

2)我必须添加gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:方法到我的视图控制器(我的手势代表)并返回YES。这使我的单击手势即使在UIWebView中显示HTML,文本或图像内容时也能做出响应,该UIWebView实现了自己对这些内容类型的手势。我从this answer了解到这部分。

有了这些变化,我明白了事件的层次是:

  • 单抽头网站的观点:我对Web视图的父视图单敲击手势响应;如果适用,网页视图的单击手势也会作出响应,因为同时启用了手势

  • 双击web视图:我在web视图的父视图中的双击手势响应(但不执行任何操作);我的单击手势不响应,因为它配置为仅在双击失败时才响应; 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; 
} 
+0

谢谢你的回答。它最接近我的情况并提供解决方案,读了十几篇文章后。非常安静的工作。 – vedrano 2013-04-02 22:26:05

+0

肯定+1。很好的解释和良好的代码,经过Swift 2.1的测试和工作 – 2016-03-21 14:44:35

-2

自事件处理开始以来,始终是鼠标点击的问题。

在一次点击的情况下,任何软件都无法确定双击即将发生,这是不可能的。

所以,如果你想处理单击和双击,你必须做你自己的双击处理。

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

希望这可以转移到您的情况下攻丝。

+0

实际上,在iOS中,UIGestureRecognizer具有内置功能,可以在触发单击事件之前等待双击的持续时间。这就是为什么我可以使用两个不同的手势识别器正确捕捉这两个事件。我只是不知道如何忽略双击手势,以便它到达UIWebView或将其重定向到那里,以保留Web视图的内置缩放行为。 – arlomedia 2012-07-17 04:24:18

+0

@arlomedia [iOS事件转发](https://www.google.com/search?btnG=1&pws=0&q=iOS+event+forwarding) – 2012-07-17 14:45:46

+0

我浏览了那些搜索结果,但没有看到任何有助于我的内容情况。我确实看到了一些建议,我不应该尝试将事件转发到UIKit对象,这会让我回到我的问题的“也许有更简单的方法”的一部分。 – arlomedia 2012-07-17 15:13:07