代码之家  ›  专栏  ›  技术社区  ›  pgb

检测UIWebView中的点击

  •  7
  • pgb  · 技术社区  · 15 年前

    UIWebView 带有导航栏和我想自动隐藏的工具栏。我已经在做了,但是我想在用户点击 UIWebView

    UIWebView

    有什么解决办法吗?

    8 回复  |  直到 15 年前
        1
  •  8
  •   Dan Abramov    11 年前

    blog entry Google Cache'd )借 Mithin Kumar .

    (米钦,我希望你不介意我把它转载到这里;如果你介意,请在评论中告诉我,我会删除它。)

    here

    1. 复制/选择停止在UIWebView上工作
    2. 我们需要创建UIWebView的一个子类,而苹果说我们不应该对它进行子类。

    对UIWindow进行子分类并重新实现-sendEvent:方法。在这里 这就是你能做到的。首先,创建一个UIWindow子类

    #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 信息。现在,用以下方法实现这个类

    #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,而不是 窗口。只有到那时,所有的事件才会通过上述程序 重新实现sendEvent方法。另外,一定要打电话给[super] sendEvent:event]然后执行任何您想要的操作。

    @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;
    }
    

    控制器类。这是为了发送而调用的方法 将事件信息发送到控制器类。在我们上面的例子中,我们 正在发送UIWebView中用户点击的点。

        2
  •  8
  •   Brody Robertson    10 年前

    你可以 非常简单 使用UIAPTgestureRecognitor检测UIWebView上的点击手势。但是,必须实现UIgestureRecognitzerDelegate方法以允许同时识别。

    - (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{
    
    
    
    }
    
        3
  •  3
  •   Community T.Woody    7 年前

    我在尝试使用时遇到了几个问题 brian.clear's answer Mithin Kumar )在我的 , 普遍的 基于情节提要 , 全弧 所以我不得不做一些改变。我还改进了一些东西,使它更容易理解(至少对我来说)。如果你在使用2009年的答案时遇到困难,也许你应该试试我的更新。详细说明:

    1.创建新的TapDetectingWindow类

    点击检测窗口

    //  Created by Cristian Perez <cpr@cpr.name>
    //  Based on https://stackoverflow.com/a/1859883/423171
    
    #import <UIKit/UIKit.h>
    
    @protocol TapDetectingWindowDelegate
    
    - (void)userDidTapView:(CGPoint)tapPoint;
    
    @end
    
    @interface TapDetectingWindow : UIWindow
    
    @property (nonatomic) UIView *tapDetectingView;
    @property (nonatomic) id <TapDetectingWindowDelegate> tapDetectedDelegate;
    
    @end
    

    点击检测窗口

    //  Created by Cristian Perez <cpr@cpr.name>
    //  Based on https://stackoverflow.com/a/1859883/423171
    
    #import "TapDetectingWindow.h"
    
    @implementation TapDetectingWindow
    
    @synthesize tapDetectingView;
    @synthesize tapDetectedDelegate;
    
    - (id)initWithFrame:(CGRect)frame
    {
        return [super initWithFrame:frame];
    }
    
    - (void)sendEvent:(UIEvent *)event
    {
        [super sendEvent:event];
        if (tapDetectingView == nil || tapDetectedDelegate == nil)
        {
            return;
        }
        NSSet *touches = [event allTouches];
        if (touches.count != 1)
        {
            return;
        }
        UITouch *touch = touches.anyObject;
        if (touch.phase != UITouchPhaseEnded)
        {
            return;
        }
        if (touch.view != nil && ![touch.view isDescendantOfView:tapDetectingView])
        {
            return;
        }
        CGPoint tapPoint = [touch locationInView:tapDetectingView];
        NSString *tapPointStr = NSStringFromCGPoint(tapPoint);
        if (touch.tapCount == 1)
        {
            [self performSelector:@selector(notifyTap:) withObject:tapPointStr afterDelay:0.4];
            // Make the afterDelay value bigger in order to have more chances of detecting a double tap and thus being able to cancel the single tap event, or make it smaller if you don't care about double taps and want to get the tap event as soon as possible
        }
        else if (touch.tapCount > 1)
        {
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(notifyTap:) object:tapPointStr];
        }
    }
    
    - (void)notifyTap:(NSString *)tapPointStr
    {
        CGPoint tapPoint = CGPointFromString(tapPointStr);
        [tapDetectedDelegate userDidTapView:tapPoint];
    }
    
    @end
    

    window 在应用程序代理中声明

    你应该有这样的东西在里面 YourAppDelegate.h . 不要更改属性的名称!

    @interface YourAppDelegate : UIResponder <UIApplicationDelegate>
    {
        // ...
    }
    
    // ...
    
    // The app delegate must implement the window property if it wants to use a main storyboard file
    @property (nonatomic) UIWindow *window;
    
    @end
    

    3.覆盖 窗口 应用程序代理的属性

    YourAppDelegate.m

    // Replace the default UIWindow property with a TapDetectingWindow
    - (TapDetectingWindow *)window
    {
        static TapDetectingWindow *tapDetectingWindow = nil;
        if (!tapDetectingWindow)
        {
            tapDetectingWindow = [[TapDetectingWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        }
        return tapDetectingWindow;
    }
    

    4.在视图控制器中设置代理协议

    MainViewController.h

    #import "TapDetectingWindow.h"
    
    @interface MainViewController : UIViewController <TapDetectingWindowDelegate, ...>
    {
        // ...
    }
    
    // ...
    
    @end
    

    5.设置点击检测窗口和点击事件处理程序

    指定您的webview(实际上任何UIView都应该工作),并在视图控制器的窗口中点击事件处理程序 方法

    - (void)viewDidLoad
    {
        // ...
    
        // Allow tap detection in webview
        TapDetectingWindow *tapDetectingWindow = (TapDetectingWindow*)[(YouTubeRPAppDelegate*)[[UIApplication sharedApplication] delegate] window];
        tapDetectingWindow.tapDetectingView = self.webView; // Your UIWebView
        tapDetectingWindow.tapDetectedDelegate = self;
    }
    

    6.根据需要处理tap事件

    只需执行 视图控制器中的方法

    - (void)userDidTapView:(CGPoint)tapPoint
    {
        NSLog(@"Tap detected in webview at %@", NSStringFromCGPoint(tapPoint));
    }
    
        4
  •  1
  •   Community T.Woody    7 年前

    大多数方法都处理一对复杂的 UIView UIWebView -touchesBegan:withEvent: 等等。方法。

    This JavaScript-based approach

        5
  •  1
  •   Michael Waterfall    15 年前

        6
  •  1
  •   Sayeed S. Alam    13 年前

    创建一个 UIView 包含整体的子类 UIWebView

    @interface myWebViewContainer : UIView
    ... ...
    @end
    

    然后覆盖hitTest事件:

    -(UIView*) hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
        NSLog(@"Hit test %@", [event description]);
        UIView * returnView = [super hitTest:point withEvent:event];
        [delegate userDidTapWebView];// notify the delegate that UIWebView is being touched by some naughty user :P
    
    
        return  returnView;
    }
    
        7
  •  0
  •   DonnaLea    12 年前

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        UITapGestureRecognizer* tapGestureRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self 
                                                                                            action:@selector(userDidTapWebView)] autorelease];
        [self.pdfWebView addGestureRecognizer:tapGestureRecognizer];
    
    }
    
    - (void)userDidTapWebView {
        NSLog(@"TAP");
    }