我有一个UIWebView导航栏和工具栏,我想自动隐藏.我已经这样做了,但我想在用户点击时显示它们UIWebView.
我的问题是UIWebView捕获所有触摸事件,我无法拦截我需要的那个.
这有什么解决方法吗?
来自Mithin Kumar的博客文章(不加载,但谢天谢地,它是谷歌缓存).
(Mithin,我希望你不介意我把它转发到这里;如果你这样做,请在评论中告诉我,我会将其删除.)
最近,我正在开发一个需要在UIWebView上检测tap和事件的项目.我们想要找出用户在UIWebView中点击的HTML元素,然后根据点击的元素执行一些操作.经过一些谷歌搜索,我发现大多数用户在UIWebView上面放置一个透明的UIView,重新实现UIResponder类的触摸方法(例如:-touchesBegan:withEvent :),然后将事件传递给UIWebView.这里详细解释了这种方法.该方法存在多个问题.
- 复制/选择停止在UIWebView上工作
- 我们需要创建UIWebView的子类,而Apple说我们不应该对它进行子类化.
- 许多其他UIWebView功能停止工作.
我们最终发现实现这一点的正确方法是通过对UIWindow进行子类化并重新实现-sendEvent:方法.这是你如何做到的.首先,创建一个UIWindow子类
Run Code Online (Sandbox Code Playgroud)#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请注意,我们有变量告诉我们检测事件的UIView和接收事件信息的控制器.现在,按以下方式实现此类
Run Code Online (Sandbox Code Playgroud)#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
Run Code Online (Sandbox Code Playgroud)@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; }请记住,您需要在控制器类中编写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{
}
Run Code Online (Sandbox Code Playgroud)
大多数方法处理一对复杂的子类UIView和UIWebView重写-touchesBegan:withEvent:等方法。
这种基于 JavaScript 的方法拦截对 Web DOM 本身的接触,这似乎是回避更复杂过程的聪明方法。我自己还没有尝试过,但如果你尝试一下,我很想知道结果。
| 归档时间: |
|
| 查看次数: |
15131 次 |
| 最近记录: |