如何在UIWebView中响应双击事件
2014-12-23
展开全部
单击事件
通常单击的解决方案是用javascript实现, 为html元素绑定onclick事件, javascript接收事件后跳转url, 在CocoaTouch中用 webView:shouldStartLoadWithRequest:navigationType: 拦截url跳转, 从而实现单击事件的响应, 大致的代码如下:
Javascript:
function myClick() {
var e = window.event
var url = "click:" + e.target.id;
document.location = url;
}
var ele = document.getElementById(ELEMENT_ID);
ele.onclick = myClick;
CocoaTouch:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:@":"];
if (components.count == 2 && [(NSString *)[components objectAtIndex:0] isEqualToString:@"click"]) {
NSString *eleIdStr = (NSString *)[components objectAtIndex:1];
NSInteger eleId = [eleIdStr integerValue];
// Do something
return NO; // Do not load request, just receive the event
}
return YES;
}
双击事件
Failed 1
使用与上面同样的方法为html元素添加ondblclick来响应双击事件就无法实现, 现象为响应函数从不被调用. 用setTimeout等方法尝试用单击事件来模拟双击事件也无法实现, 无法接收到double tap的第二次点击.
Failed 2
根据之前的现象来看, 显然双击事件在html之外就被拦截了, 要从CocoaTouch层下手才行.
系统的UIWebView中包含了一个UIScrollView, 绑定了UIScrollViewDelayedTouchesBeganGestureRecognizer和UIScrollViewPanGestureRecognizer这两个事件, 后者响应拖动事件, 前者相应点击事件.
尝试添给UIScrollView加UITapGestureRecognizer:
UITapGestureRecognizer *dblTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fakeTapGestureHandler:)];
经测试, fakeTapGestureHandler:从未被调用过.
Success
尝试曲线救国的方式, 用UIGestureRecognizer的delegate方法获取事件:
Javascript:
function eleIdFromPoint(x, y) {
var ele = document.elementFromPoint(x, y)
return "" + ele.id;
}
CocoaTouch:
// Add gesture
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fakeTapGestureHandler:)];
[tapGestureRecognizer setDelegate:self];
[_webView.scrollView addGestureRecognizer:tapGestureRecognizer];
// Delegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint tapPoint = [touch locationInView:_webView];
NSString *script = [NSString stringWithFormat:@"eleIdFromPoint(%f, %f)", tapPoint.x, tapPoint.y];
NSString *eleIdStr = [self stringByEvaluatingJavaScriptFromString:script];
if (touch.tapCount == 2) {
if (eleIdStr.length > 0) {
NSInteger eleId = [eleIdStr integerValue];
// Do somthing
}
}
return YES; // Return NO to prevent html document from receiving the touch event.
}
上面代码通过UIGestureRecognizer的delegate方法成功获取到点击事件, 需要说明的几点:
locationInView:的参数为UIWebView, 后面的document.elementFromPoint传递的也是UIWebView中对应的坐标, 不需要算上UIScrollView的Offset.
delegate方法中单击事件也可以被拦截到, 这样单击双击就可以在这块儿一起实现, 让代码看起来比较统一.
delegate方法返回NO会拦截事件, html文档就不能接受到任何点击事件了.
通常单击的解决方案是用javascript实现, 为html元素绑定onclick事件, javascript接收事件后跳转url, 在CocoaTouch中用 webView:shouldStartLoadWithRequest:navigationType: 拦截url跳转, 从而实现单击事件的响应, 大致的代码如下:
Javascript:
function myClick() {
var e = window.event
var url = "click:" + e.target.id;
document.location = url;
}
var ele = document.getElementById(ELEMENT_ID);
ele.onclick = myClick;
CocoaTouch:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:@":"];
if (components.count == 2 && [(NSString *)[components objectAtIndex:0] isEqualToString:@"click"]) {
NSString *eleIdStr = (NSString *)[components objectAtIndex:1];
NSInteger eleId = [eleIdStr integerValue];
// Do something
return NO; // Do not load request, just receive the event
}
return YES;
}
双击事件
Failed 1
使用与上面同样的方法为html元素添加ondblclick来响应双击事件就无法实现, 现象为响应函数从不被调用. 用setTimeout等方法尝试用单击事件来模拟双击事件也无法实现, 无法接收到double tap的第二次点击.
Failed 2
根据之前的现象来看, 显然双击事件在html之外就被拦截了, 要从CocoaTouch层下手才行.
系统的UIWebView中包含了一个UIScrollView, 绑定了UIScrollViewDelayedTouchesBeganGestureRecognizer和UIScrollViewPanGestureRecognizer这两个事件, 后者响应拖动事件, 前者相应点击事件.
尝试添给UIScrollView加UITapGestureRecognizer:
UITapGestureRecognizer *dblTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fakeTapGestureHandler:)];
经测试, fakeTapGestureHandler:从未被调用过.
Success
尝试曲线救国的方式, 用UIGestureRecognizer的delegate方法获取事件:
Javascript:
function eleIdFromPoint(x, y) {
var ele = document.elementFromPoint(x, y)
return "" + ele.id;
}
CocoaTouch:
// Add gesture
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fakeTapGestureHandler:)];
[tapGestureRecognizer setDelegate:self];
[_webView.scrollView addGestureRecognizer:tapGestureRecognizer];
// Delegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint tapPoint = [touch locationInView:_webView];
NSString *script = [NSString stringWithFormat:@"eleIdFromPoint(%f, %f)", tapPoint.x, tapPoint.y];
NSString *eleIdStr = [self stringByEvaluatingJavaScriptFromString:script];
if (touch.tapCount == 2) {
if (eleIdStr.length > 0) {
NSInteger eleId = [eleIdStr integerValue];
// Do somthing
}
}
return YES; // Return NO to prevent html document from receiving the touch event.
}
上面代码通过UIGestureRecognizer的delegate方法成功获取到点击事件, 需要说明的几点:
locationInView:的参数为UIWebView, 后面的document.elementFromPoint传递的也是UIWebView中对应的坐标, 不需要算上UIScrollView的Offset.
delegate方法中单击事件也可以被拦截到, 这样单击双击就可以在这块儿一起实现, 让代码看起来比较统一.
delegate方法返回NO会拦截事件, html文档就不能接受到任何点击事件了.
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询