Iphone UIGestureRecognitor在UIWebView上工作吗?

Iphone UIGestureRecognitor在UIWebView上工作吗?,iphone,objective-c,cocoa,ipad,uigesturerecognizer,Iphone,Objective C,Cocoa,Ipad,Uigesturerecognizer,我正在尝试使用UIGestureRecognitor处理UIWebview,它是UIScrollView的子视图。这听起来很奇怪,但是当我将numberOfTouchesRequired设置为2时,选择器会启动,但当numberOfTouchesRequired设置为1时,选择器不会启动 这是我的密码: UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@select

我正在尝试使用UIGestureRecognitor处理UIWebview,它是UIScrollView的子视图。这听起来很奇怪,但是当我将
numberOfTouchesRequired
设置为2时,选择器会启动,但当
numberOfTouchesRequired
设置为1时,选择器不会启动

这是我的密码:

UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(select1:)];
    tap1.numberOfTouchesRequired = 2;
    tap1.numberOfTapsRequired = 1;
    tap1.delegate = self;
    [self.ans1WebView addGestureRecognizer:tap1];
    [tap1 release];

- (void) select1:(UILongPressGestureRecognizer *)sender {
    //Do Stuff
}

我已经通过使用苹果UIgestureRecognitor示例并在他们的nib中插入webview来证实了这一点。他们的tap代码在任何地方都能工作,但在webview区域内除外。

从我所看到的情况来看,UIWebView不能很好地与其他人合作。对于手势识别器,您可以尝试从以下位置返回“是”:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
我必须向后兼容3.0,因此我最终在UIWebView中使用Javascript完成所有手势处理。这不是一个好的解决方案,但它满足了我的需要。我能够捕捉到一个元素上的长按,以及点击、滑动、捏和旋转。当然,我只使用了本地内容

编辑:

您可以查看向UIWebView的代理发送消息的示例。简而言之,您可以使用
document.location=“myscheme:mycommand?myarguments”
然后从该委托回调解析出命令和参数:

-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
  if ( [[[inRequest URL] absoluteString] hasPrefix:@"myscheme:"] ) {
    //.. parse arguments
    return NO;
  }
}
您可以在PhoneGap代码中看到,他们设置了一个队列和计时器来发送消息。根据您的使用情况,您可能需要执行相同的操作。关于这个话题还有其他问题

这是文件。在我的例子中,我将事件侦听器从

实际的事件处理在很大程度上取决于您的需要。每个事件处理程序将接收一个带有touchs属性的,其中每个项目都是一个。您可以在touchstart处理程序中记录开始时间和位置。如果触摸移动到远处或经过的时间不正确,则不是长时间触摸

WebKit可能会尝试长时间触摸以开始选择和复制。在事件处理程序中,可以使用
event.preventDefault()
停止默认行为。我还发现
-webkit user select:none
css属性在某些方面很方便

var touch = {};
function touch_start( event /*TouchEvent*/ {
  event.preventDefault();
  touch = {};
  touch.startX = event.touches.item(0).pageX;
  touch.startY = event.touches.item(0).pageY;
  touch.startT = ( new Date() ).getTime();
}
这只是我使用javascript的第二个项目。你可以在别处找到更好的例子


正如你所见,这并不是你问题的快速答案。我对我得到的结果很满意。我使用的html除了一两个链接之外没有任何交互元素。

你可能会发现我的答案很有用。这是一个在UIWebView的javascript中处理挤压手势的工作示例


(如果愿意,您可以将事件传回Objective-C。请参阅。)

UIWebView有自己的私有视图,还附带了手势识别器。因此,优先级规则会阻止添加到UIWebView的任何手势识别器正常工作

一个选项是实现UIGestureRecognitzerDelegate协议,并实现方法GestureRecognitzer:shouldRecognitizeSimultaneouswithGestureRecognitzer。对于其他点击手势,使用此方法返回YES。通过这种方式,您将调用tap处理程序,并且web视图仍将被调用


我也有同样的问题。这个解决方案对我有效:

1) 确保将协议添加到接口:UIgestureRecognitzerDelegate,例如:

@interface ViewController : UIViewController <SlideViewProtocol, UIGestureRecognizerDelegate>
3) 设置手势

UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(nextSlide)];
swipeGesture.numberOfTouchesRequired = 1;
swipeGesture.direction = (UISwipeGestureRecognizerDirectionLeft);
swipeGesture.cancelsTouchesInView = YES; [swipeGesture setDelegate:self];
[self.view addGestureRecognizer:swipeGesture];

另一种方法是在UIWebView上放置一个透明的UIButton,并处理来自该按钮的点击。在某些情况下,这可能是一个很好的解决方案

UIWebView webView = [UIWebView new];
//...

UIButton *transparentButton = [UIButton buttonWithType:UIButtonTypeCustom];
[transparentButton addTarget:self action:@selector(buttonTapped) forControlEvents:(UIControlEventTouchUpInside)];
transparentButton.frame = webView.frame;
transparentButton.layer.backgroundColor = [[UIColor clearColor] CGColor];
[self.view transparentButton];

这是一个有点黑客式的解决方案,但它是有效的。 UIWebView有很多内部手势识别器,如果不使用私有API,通常无法访问这些识别器。不过,当您实现
gesturecognizer:shouldlrecognizewithgesturecognizer:
时,您可以免费获得所有这些功能。此时,您可以告诉所有内部UITapGestureRecognitor仅在您自己的UITapGestureRecognitor出现故障时触发。您只需执行一次,然后将代理从您自己的手势识别器中删除。其结果是,您仍然可以平移和滚动您的webView,但它将不再接收任何(单个)点击手势

- (void)viewDidLoad 
{      
    [super viewDidLoad];

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];

    // view is your UIViewController's view that contains your UIWebView as a subview
    [self.view addGestureRecognizer:tap];

    tap.delegate = self;
}

- (void)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer
{
    NSLog(@"tap!");

    // this is called after gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: so we can safely remove the delegate here
    if (gestureRecognizer.delegate) {
        NSLog(@"Removing delegate...");
        gestureRecognizer.delegate = nil;
    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        [otherGestureRecognizer requireGestureRecognizerToFail:gestureRecognizer];

        NSLog(@"added failure requirement to: %@", otherGestureRecognizer);
    }

    return YES;
}

享受吧

谢谢,我对Javascript一无所知;能否请您为我指出如何通过Javascript检测UIWebView中的点击并调用Objective-C方法的正确方向?对于非iPad目标,我不介意与3.0兼容。对于其他只关心3.2+的人,我只需在UIWebView上创建一个透明视图并检测其中的点击,就解决了我的问题。有关补充信息,请参阅问题中的第二个答案:应编辑此答案,以在步骤#2中返回正确的代码(即,API需要返回BOOL)。这是最简单的解决方案,对我来说很有效,但有两个注意事项。您需要返回YES。您必须设置swipgesture.delegate=self;哈哈,这绝对是最好的解决方案:)+1的黑客。我使用这种方法,如果我不需要滚动UIWebView。但是,如果需要滚动,它将无法工作,因为UIButton会捕获所有用户输入。
UIWebView webView = [UIWebView new];
//...

UIButton *transparentButton = [UIButton buttonWithType:UIButtonTypeCustom];
[transparentButton addTarget:self action:@selector(buttonTapped) forControlEvents:(UIControlEventTouchUpInside)];
transparentButton.frame = webView.frame;
transparentButton.layer.backgroundColor = [[UIColor clearColor] CGColor];
[self.view transparentButton];
- (void)viewDidLoad 
{      
    [super viewDidLoad];

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];

    // view is your UIViewController's view that contains your UIWebView as a subview
    [self.view addGestureRecognizer:tap];

    tap.delegate = self;
}

- (void)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer
{
    NSLog(@"tap!");

    // this is called after gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: so we can safely remove the delegate here
    if (gestureRecognizer.delegate) {
        NSLog(@"Removing delegate...");
        gestureRecognizer.delegate = nil;
    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        [otherGestureRecognizer requireGestureRecognizerToFail:gestureRecognizer];

        NSLog(@"added failure requirement to: %@", otherGestureRecognizer);
    }

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