UIGestureRecognizer是否可以在UIWebView上运行?

rsc*_*ott 40 iphone cocoa objective-c ipad uigesturerecognizer

我试图让UIGestureRecognizer使用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
}
Run Code Online (Sandbox Code Playgroud)

我已经通过使用Apple样本用于UIGestureRecognizer并在其笔尖中插入webview来证实了这一点.他们的tap代码可以在webview区域内的任何地方使用.

dra*_*ard 67

从我所看到的,UIWebView与其他人不一致.对于手势识别器,您可以尝试从以下位置返回YES:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
Run Code Online (Sandbox Code Playgroud)

我必须向后兼容3.0,所以我最终在UIWebView中使用Javascript进行所有手势处理.不是一个好的解决方案,但它符合我的需求.我能够在元素上捕获长按,以及点击,滑动,捏合和旋转.当然,我只使用本地内容.

编辑:

您可以在PhoneGap中查找向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;
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以在PhoneGap代码中看到他们设置了一个队列和计时器来发送消息.根据您的使用情况,您可能需要做同样的事情.关于这个主题还有其他问题.

这是事件处理文档.在我来说,我添加的事件监听器document<body onload="myloader();">

function myloader() {
    document.addEventListener( 'touchcancel' , touch_cancel , false );
    document.addEventListener( 'touchstart' , touch_start , false );
    document.addEventListener( 'touchmove' , touch_move , false );
    document.addEventListener( 'touchend' , touch_end , false );
};
Run Code Online (Sandbox Code Playgroud)

实际的事件处理很大程度上取决于您的需求.每个事件处理程序都将收到一个TouchEvent,其中包含touches属性,其中每个项目都是Touch.您可以在touchstart处理程序中记录开始时间和位置.如果触摸移动到很远或者错误的时间过去,那就不是长时间的触摸.

WebKit可能会尝试处理长时间触摸以启动选择和复制.在事件处理程序中,您可以使用它event.preventDefault();来停止默认行为.我还发现-webkit-user-select:nonecss属性对某些东西很方便.

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();
}
Run Code Online (Sandbox Code Playgroud)

这只是我用过javascript的第二个项目.你可以在别处找到更好的例子.

正如您所看到的,这不是您问题的快速答案.我对我得到的结果非常满意.我正在使用的html没有一个或两个链接之外的交互元素.

  • 谢谢,我对Javascript一无所知; 你会非常友好地指出我如何通过Javascript检测UIWebView中的点击并调用Objective-C方法吗?我不介意与非iPad目标兼容3.0.对于只关心3.2+的任何其他人,我通过简单地在UIWebView顶部创建一个透明视图并检测其中的水龙头来解决我的问题. (3认同)

Don*_*son 45

UIWebView有自己的私有视图,它还附带了手势识别器.因此,优先规则使添加到UIWebView的任何手势识别器都无法正常工作.

一种选择是实现UIGestureRecognizerDelegate协议并实现方法gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer.对于其他点按手势,从此方法返回YES.通过这种方式,您将调用您的tap控制器,并且Web视图仍将被调用.

在Apple dev论坛上看到这一点.


Joh*_*rug 13

这是一个有点黑客的解决方案,但它的工作原理.UIWebView有很多内部手势识别器,如果不使用私有API,通常无法访问.但是,当你实施时,你可以免费获得它们gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:.此时,您可以告诉所有内部UITapGestureRecognizers仅在您自己的UITapGestureRecognizer失败时触发.您只需执行一次,然后从您自己的手势识别器中删除该委托.结果是您仍然可以平移和滚动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;
}
Run Code Online (Sandbox Code Playgroud)

请享用!


chr*_*ick 5

我也遇到了同样的问题。这个解决方案对我有用:

1) 确保将协议添加到您的界面:UIGestureRecognizerDelegate 例如:

@interface ViewController : UIViewController <SlideViewProtocol, UIGestureRecognizerDelegate>
Run Code Online (Sandbox Code Playgroud)

2)添加这行代码

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES
}
Run Code Online (Sandbox Code Playgroud)

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];
Run Code Online (Sandbox Code Playgroud)