UIWebView捕捉点击事件

本文介绍了一种不通过透明UIView覆盖UIWebView,而是通过重写UIWindow的-sendEvent:方法来准确检测UIWebView上的点击事件的方法。这种方法可以避免许多常见的问题,如复制/选择功能失效等,并且不需要对UIWebView进行子类化。

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

rom:http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/

Recently, I was working on a project which required detection of tap and events on the UIWebView. We wanted to find out the HTML element on which the user taps in the UIWebView and then depending on the element tapped some action was to be performed. After some Googling, I found out the most of the users lay a transparent UIView on top of the UIWebView, re-implement the touch methods of UIResponder class (Ex: -touchesBegan:withEvent:) and then pass the events to the UIWebView. This method is explained in detail here. There are multiple problems with the method.

  1. Copy/Selection stops working on UIWebView
  2. We need to create a sub-class of UIWebView while Apple says we should not sub-class it.
  3. A lot other UIWebView features stop working.

We ultimately found out that the right way to implement this is by sub-classing UIWindow and re-implementing the -sendEvent: method. Here is how you can do it. First, create a UIWindow sub-class

#import <UIKit/UIKit.h>
@protocol TapDetectingWindowDelegate
- (void)userDidTapWebView:(id)tapPoint;
@end
@interface TapDetectingWindow : UIWindow {
    UIView *viewToObserve;
    id <TapDetectingWindowDelegate> controllerThatObserves;
}
@property (nonatomic, retain) UIView *viewToObserve;
@property (nonatomic, assign) id <TapDetectingWindowDelegate> controllerThatObserves;
@end

Note that we have variables which tell us the UIView on which to detect the events and the controller that receives the event information. Now, implement this class in the following way

#import "TapDetectingWindow.h"
@implementation TapDetectingWindow
@synthesize viewToObserve;
@synthesize controllerThatObserves;
- (id)initWithViewToObserver:(UIView *)view andDelegate:(id)delegate {
    if(self == [super init]) {
        self.viewToObserve = view;
        self.controllerThatObserves = delegate;
    }
    return self;
}
- (void)dealloc {
    [viewToObserve release];
    [super dealloc];
}
- (void)forwardTap:(id)touch {
    [controllerThatObserves userDidTapWebView:touch];
}
- (void)sendEvent:(UIEvent *)event {
    [super sendEvent:event];
    if (viewToObserve == nil || controllerThatObserves == nil)
        return;
    NSSet *touches = [event allTouches];
    if (touches.count != 1)
        return;
    UITouch *touch = touches.anyObject;
    if (touch.phase != UITouchPhaseEnded)
        return;
    if ([touch.view isDescendantOfView:viewToObserve] == NO)
        return;
    CGPoint tapPoint = [touch locationInView:viewToObserve];
    NSLog(@"TapPoint = %f, %f", tapPoint.x, tapPoint.y);
    NSArray *pointArray = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%f", tapPoint.x],
    [NSString stringWithFormat:@"%f", tapPoint.y], nil];
    if (touch.tapCount == 1) {
        [self performSelector:@selector(forwardTap:) withObject:pointArray afterDelay:0.5];
    }
    else if (touch.tapCount > 1) {
        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(forwardTap:) object:pointArray];
    }
}
@end

Implement the sendEvent method in the above way, and then you can send back the information you want back to the controller. There are few things that one needs to keep in mind. Make sure in your MainWindow.xib file, the window is of type TapDetectingWindow and not UIWindow. Only then all the events will pass through the above re-implemented sendEvent method. Also, make sure you call [super sendEvent:event] first and then do whatever you want. Now, you can create your UIWebView in the controller class in the following way

@interface WebViewController : UIViewController<TapDetectingWindowDelegate> {
    IBOutlet UIWebView *mHtmlViewer;
    TapDetectingWindow *mWindow;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    mWindow = (TapDetectingWindow *)[[UIApplication sharedApplication].windows objectAtIndex:0];
    mWindow.viewToObserve = mHtmlViewer;
    mWindow.controllerThatObserves = self;
}

转载于:https://www.cnblogs.com/pengyingh/articles/2502085.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值