获取UIWebView的touch事件

UIWebView会阻挡其下方UIViewController.view的触摸事件。一种解决方案是创建一个透明的UIView子类,覆盖在webview上。另一种方法是创建UIWindow子类TouchCapturingWindow,重写sendEvent方法来自定义事件传递。此外,更新说明使用JavaScript可以更方便地获取UIWebView的touch事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UIWebView作为一个UIViewController的子视图,会遮挡住这个viewcotroller.view的touch事件,不能向下传递。在网上搜索了下,常用解决方法:创建UIView子类,重写touchesBegan等方法,添加这个类的实例放在webview上面,并设置为透明。

下面介绍另一个方法:创建UIWindow的子类 TouchCapturingWindow,重写sendEvent方法,自定义哪个View来决定接收Touch。

TouchCapturingWindow.h

#import <UIKit/UIKit.h>

@interface TouchCapturingWindow : UIWindow {
    NSMutableArray *views;
    
@private
    UIView *touchView;
}

- (void)addViewForTouchPriority:(UIView*)view;
- (void)removeViewForTouchPriority:(UIView*)view;

@end

TouchCapturingWindow.m

#import "TouchCapturingWindow.h"

@implementation TouchCapturingWindow

- (void)addViewForTouchPriority:(UIView*)view {
    if ( !views ) views = [[NSMutableArray alloc] init];
    [views addObject:view];
}

- (void)removeViewForTouchPriority:(UIView*)view {
    if ( !views ) return;
    [views removeObject:view];
}

- (void)sendEvent:(UIEvent *)event {
    //get a touch
    UITouch *touch = [[event allTouches] anyObject];
    
    //check which phase the touch is at, and process it
    if (touch.phase == UITouchPhaseBegan) {
        for ( UIView *view in views ) {
            //NOTE: I added the isHidden check so that hiding the windows doesn't catch events
            //and changed it checks if the touch is in the frame.
            //if ( CGRectContainsPoint([view frame], [touch locationInView:[view superview]]) ) {
            if ( ![view isHidden] && [view pointInside:[touch locationInView:view] withEvent:event] ) {
                touchView = view;
                [touchView touchesBegan:[event allTouches] withEvent:event];
                break; //NOTE: this used to be a return in the previous version
            }
           }
        }
    else if (touch.phase == UITouchPhaseMoved) {
        if ( touchView ) {
            [touchView touchesMoved:[event allTouches] withEvent:event];
            }
        }
    else if (touch.phase == UITouchPhaseCancelled) {
        if ( touchView ) {
            [touchView touchesCancelled:[event allTouches] withEvent:event];
            touchView = nil;
            }
        }
    else if (touch.phase == UITouchPhaseEnded) {
        if ( touchView ) {
            [touchView touchesEnded:[event allTouches] withEvent:event];
            touchView = nil;
            }
        }
    //we need to send the message to the super for the
    //text overlay to work (holding touch to show copy/paste)
    [super sendEvent:event];
}


使用:在AppDelegate初始化UIWindow时,将TouchCapturingWindow的实例对象赋值给window

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window =  [[TouchCapturingWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // ...
}


在viewController中使用

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.youkuaiyun.com"]];
    [self.webView loadRequest:request];
    
    mWindow = (TouchCapturingWindow *)[[UIApplication sharedApplication].windows objectAtIndex:0];
    [mWindow addViewForTouchPriority:self.webView];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@" == touchesBegan ==");
}

大功告成,点击webview或其他subview,都可以在viewcontroller中接收到touch处理事件。

注:一般的UIView类和其子类直接设置setUserInteractionEnabled为NO即可。


------------------ 2013.7.17 更新 -----------------------

用js可以更方便获得来自UIWebView的touch事件,实例代码

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    self.webview.delegate=self;
    NSString *resourcePath = [ [NSBundle mainBundle] resourcePath];
    NSString *filePath = [resourcePath stringByAppendingPathComponent:@"test.html"];
    NSString *htmlstring=[[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    NSString *newHTMLString=[htmlstring stringByAppendingString:@"<script language=\"javascript\">document.ontouchstart=function(){document.location=\"myweb:touch:start\";}; document.ontouchend=function(){document.location=\"myweb:touch:end\";}; document.ontouchmove=function(){document.location=\"myweb:touch:move\";}</script>"];
    [self.webview loadHTMLString:newHTMLString baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
}

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *requestString = [[request URL] absoluteString];
    
    NSArray *components = [requestString componentsSeparatedByString:@":"];
    if ([components count] > 1 && [(NSString *)[components objectAtIndex:0] isEqualToString:@"myweb"]) {
        if([(NSString *)[components objectAtIndex:1] isEqualToString:@"touch"])
            {
                NSLog(@"%@",[components objectAtIndex:2]);
                }
        return NO;
        }
    return YES;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值