滑动手势识别UIWebView

问题描述:

我已经阅读了一堆关于这个问题,但没有一个人似乎达到我在找什么...因此,可以说我有一个UIWebView任意UIViewController内。 UIViewController有一个SwipeGestureRecognizer工作正常。它甚至可以在UIWebView内工作 - 只要没有滚动条。 (在我加载页面之前,或者即使我加载了一个页面,可以在我的UIWebView的尺寸范围内适当放置)。但是,如果我加载需要向左或向右水平滚动的网页,则在我的视图的部分内容中,我无法获取任何轻扫手势进行识别。每次点击/拖拽/轻扫只会触发滚动操作。有没有办法区分“滑动”和只用手指滚动(不是解除它,而是拖动滚动)。滑动手势识别UIWebView

您将不得不继承UIWebView并覆盖手势识别器调用。

编辑 - 看看这个帖子Handling touches inside UIWebview而这个链接http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/

+2

你能描述一下怎么去解决这个问题吗?在文档中说“UIWebView类不应该被分类”。 http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebView_Class/Reference/Reference.html – MrHappyAsthma 2012-08-08 16:51:23

+0

看看编辑 – 2012-08-08 16:56:08

是的,你可以告诉一个UIWebView的UIScrollView的,其UIPanGestureRecognizer应该只火的时候自己UISwipeGestureRecognizer失败。

这是你如何做到这一点:

UISwipeGestureRecognizer *rightSwipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)]; 
UISwipeGestureRecognizer *leftSwipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)]; 
rightSwipeGesture.direction = UISwipeGestureRecognizerDirectionRight; 
leftSwipeGesture.direction = UISwipeGestureRecognizerDirectionLeft; 
[self.view addGestureRecognizer:rightSwipeGesture]; 
[self.view addGestureRecognizer:leftSwipeGesture]; 

[_webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:rightSwipeGesture]; 
[_webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:leftSwipeGesture]; 

这应该为你做的伎俩。

+1

工作恰到好处。 – 2013-09-30 15:57:55

+1

天才,救了我很多时间! – 2015-06-25 07:52:35

+1

我没有测试过这个,但我想它会覆盖UIWebview的默认滚动。这不正确吗? – 2016-04-22 08:20:55

Johannes Fahrenkrug's answer成功有条件地阻止了webView的内置平移手势。但是,我发现这只在webView的平移手势非常慢时才起作用......如果我以合理的速度平移webView,则会触发滑动手势。我只想要快速滑动来触发滑动手势,而中等或慢速滑动可以使用默认的webView滚动功能。

的UISwipeGestureRecognizer有定制刷卡的速度没有属性,而UIPanGestureRecognizer的速度是财产,但没有办法设置要求的速度,所以我建立基于this tutorial自定义手势识别:

FastSwipeGestureRecognizer.h

#import <UIKit/UIKit.h> 
#import <UIKit/UIGestureRecognizerSubclass.h> 

#define REQUIRED_TOUCHES 5 
#define REQUIRED_STRAIGHTNESS 3 
#define REQUIRED_TIME .1 

typedef enum { 
    DirectionUp = 0, 
    DirectionRight, 
    DirectionDown, 
    DirectionLeft 
} Direction; 

@interface FastSwipeGestureRecognizer : UIGestureRecognizer { 
    CGPoint firstTouchLocation; 
    NSTimeInterval firstTouchTime; 
    int touchesCount; 

    Direction direction; 
} 

@property (nonatomic) CGPoint firstTouchLocation; 
@property (nonatomic) NSTimeInterval firstTouchTime; 
@property (nonatomic) int touchesCount; 

@property (nonatomic) Direction direction; 

@end 

FastSwipeGestureRecognizer.m

#import "FastSwipeGestureRecognizer.h" 

@implementation FastSwipeGestureRecognizer 

@synthesize firstTouchLocation; 
@synthesize firstTouchTime; 
@synthesize touchesCount; 

-(void)reset { 
    [super reset]; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesBegan:touches withEvent:event]; 
    self.firstTouchLocation = [[touches anyObject] locationInView:self.view]; 
    self.firstTouchTime = [NSDate timeIntervalSinceReferenceDate]; 
    self.touchesCount = 1; 
    self.state = UIGestureRecognizerStatePossible; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesMoved:touches withEvent:event]; 
    self.touchesCount++; 
    if (self.touchesCount > REQUIRED_TOUCHES) { // wait until we have a few touches before we evaluate the gesture 
     CGPoint thisTouchLocation = [[touches anyObject] locationInView:self.view]; 
     float horizontalRatio = (ABS(thisTouchLocation.x - self.firstTouchLocation.x)/ABS(thisTouchLocation.y - self.firstTouchLocation.y)); 
     float verticalRatio = 1/horizontalRatio; 
     NSTimeInterval elapsedTime = [NSDate timeIntervalSinceReferenceDate] - self.firstTouchTime; 
     NSLog(@"swipe? %f, %f, %f", verticalRatio, horizontalRatio, elapsedTime); 

     // if we're moving straight enough and fast enough, complete the gesture 
     if (((horizontalRatio > REQUIRED_STRAIGHTNESS)||(verticalRatio > REQUIRED_STRAIGHTNESS))&&(elapsedTime < REQUIRED_TIME)) { 
      if (horizontalRatio > REQUIRED_STRAIGHTNESS) { 
       self.direction = (thisTouchLocation.x > self.firstTouchLocation.x) ? DirectionRight : DirectionLeft ; 
      } else if (verticalRatio > REQUIRED_STRAIGHTNESS) { 
       self.direction = (thisTouchLocation.y > self.firstTouchLocation.y) ? DirectionDown : DirectionUp ; 
      } 
      self.state = UIGestureRecognizerStateRecognized; 
     } else { 
      self.state = UIGestureRecognizerStateFailed; 
     } 
    } 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesEnded:touches withEvent:event]; 
    if (self.touchesCount < REQUIRED_TOUCHES) { 
     self.state = UIGestureRecognizerStateFailed; 
    } 
} 

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesCancelled:touches withEvent:event]; 
    self.state = UIGestureRecognizerStateFailed; 
} 

@end 

设置你的手势

FastSwipeGestureRecognizer *swipeGesture = [[FastSwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)]; 
[self.view addGestureRecognizer:swipeGesture]; 
[self.webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeGesture]; 

然后检测接收到的手势

- (void)handleSwipeGesture:(FastSwipeGestureRecognizer *)gesture { 
    if (gesture.state == UIGestureRecognizerStateEnded) { 
     if (gesture.direction == DirectionRight) { 
      // do something 
     } else if (gesture.direction == DirectionLeft) { 
      // do something 
     } else if (gesture.direction == DirectionUp) { 
      // do something 
     } else if (gesture.direction == DirectionDown) { 
      // do something 
     } 
    } 
} 

注意的方向,这个只需要一个手势来处理所有四个刷卡方向,而不是每个方向一个UISwipeGestureRecognizer。