我有一个UIWebView
导航栏和工具栏,我想自动隐藏.我已经这样做了,但我想在用户点击时显示它们UIWebView
.
我的问题是UIWebView
捕获所有触摸事件,我无法拦截我需要的那个.
这有什么解决方法吗?
来自Mithin Kumar的博客文章(不加载,但谢天谢地,它是谷歌缓存).
(Mithin,我希望你不介意我把它转发到这里;如果你这样做,请在评论中告诉我,我会将其删除.)
最近,我正在开发一个需要在UIWebView上检测tap和事件的项目.我们想要找出用户在UIWebView中点击的HTML元素,然后根据点击的元素执行一些操作.经过一些谷歌搜索,我发现大多数用户在UIWebView上面放置一个透明的UIView,重新实现UIResponder类的触摸方法(例如:-touchesBegan:withEvent :),然后将事件传递给UIWebView.这里详细解释了这种方法.该方法存在多个问题.
复制/选择停止在UIWebView上工作
我们需要创建UIWebView的子类,而Apple说我们不应该对它进行子类化.
许多其他UIWebView功能停止工作.
我们最终发现实现这一点的正确方法是通过对UIWindow进行子类化并重新实现-sendEvent:方法.这是你如何做到的.首先,创建一个UIWindow子类
#import@protocol TapDetectingWindowDelegate - (void)userDidTapWebView:(id)tapPoint; @end @interface TapDetectingWindow : UIWindow { UIView *viewToObserve; id controllerThatObserves; } @property (nonatomic, retain) UIView *viewToObserve; @property (nonatomic, assign) id controllerThatObserves; @end 请注意,我们有变量告诉我们检测事件的UIView和接收事件信息的控制器.现在,按以下方式实现此类
#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以上述方式实现sendEvent方法,然后您可以将所需信息发送回控制器.
人们需要记住的事情很少.确保在MainWindow.xib文件中,窗口的类型为TapDetectingWindow,而不是UIWindow.只有这样,所有事件才会通过上面重新实现的sendEvent方法.另外,请确保先调用[super sendEvent:event],然后执行任何操作.
现在,您可以通过以下方式在控制器类中创建UIWebView
@interface WebViewController : UIViewController{ IBOutlet UIWebView *mHtmlViewer; TapDetectingWindow *mWindow; } - (void)viewDidLoad { [super viewDidLoad]; mWindow = (TapDetectingWindow *)[[UIApplication sharedApplication].windows objectAtIndex:0]; mWindow.viewToObserve = mHtmlViewer; mWindow.controllerThatObserves = self; } 请记住,您需要在控制器类中编写userDidTapWebView方法.这是为了将事件信息发送到控制器类而调用的方法.在我们的上面的例子中,我们在UIWebView中发送用户点击的点.
您可以非常简单地使用UITapGestureRecognizer来检测UIWebView上的轻击手势.您必须实现UIGestureRecognizerDelegate方法以允许同时识别.
- (void)viewDidLoad{ [super viewDidLoad]; UITapGestureRecognizer *targetGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; targetGesture.numberOfTapsRequired = 2; targetGesture.delegate = self; [self.webView addGestureRecognizer:targetGesture]; } // called when the recognition of one of gestureRecognizer or otherGestureRecognizer would be blocked by the other // return YES to allow both to recognize simultaneously. the default implementation returns NO (by default no two gestures can be recognized simultaneously) // // note: returning YES is guaranteed to allow simultaneous recognition. returning NO is not guaranteed to prevent simultaneous recognition, as the other gesture's delegate may return YES - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ NSLog(@"%@", otherGestureRecognizer); //if you would like to manipulate the otherGestureRecognizer here is an example of how to cancel and disable it if([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]){ UITapGestureRecognizer *tapRecognizer = (UITapGestureRecognizer*)otherGestureRecognizer; if(tapRecognizer.numberOfTapsRequired == 2 && tapRecognizer.numberOfTouchesRequired == 1){ //this disalbes and cancels all other singleTouchDoubleTap recognizers // default is YES. disabled gesture recognizers will not receive touches. when changed to NO the gesture recognizer will be cancelled if it's currently recognizing a gesture otherGestureRecognizer.enabled = NO; } } return YES; } -(void)handleTap:(id)sender{ }