2012-08-08 26 views
6

He leído un montón de preguntas sobre esto pero ninguno de ellos parece lograr lo que estoy buscando ... Así que digamos que tengo un UIWebView arbitrario dentro de un UIViewController. El UIViewController tiene un SwipeGestureRecognizer que funciona bien. Incluso funciona dentro del UIWebView - siempre que no haya una barra de desplazamiento. (Antes de cargar una página o incluso si cargo una página que puede caber apropiadamente dentro del tamaño de mi UIWebView). Sin embargo, si cargo una página web que requiere desplazamiento horizontal hacia la izquierda o hacia la derecha, dentro de la parte UIWebView de mi vista, no puedo obtener ningún gesto para reconocer. Cada clic/arrastrar/deslizar solo desencadena la acción de desplazamiento. ¿Hay alguna forma de diferenciar entre "deslizar" y simplemente desplazarse con el dedo (no levantarlo sino arrastrarlo para desplazarse).Swipe Gesture Recognition Inside UIWebView

Respuesta

2

Deberá subclasificar UIWebView y anular las llamadas al reconocedor de gestos.

EDITAR - Mira este post Handling touches inside UIWebview y este vínculo http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/

+2

¿Podría describir cómo hacerlo? En la documentación, dice "La clase UIWebView no se debe subclasificar". http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebView_Class/Reference/Reference.html – MrHappyAsthma

+0

Mire la edición –

24

Sí, se puede decir UIScrollView del UIWebView que su UIPanGestureRecognizer debe fuego sólo cuando su propia UISwipeGestureRecognizer ha fallado.

Así es como se hace:

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]; 

Que debe hacer el truco para usted.

+1

Funciona a la perfección. –

+1

Genius, salvó mi montón de tiempo! –

+1

No he probado esto, pero creo que anulará el desplazamiento predeterminado de UIWebview. ¿No es así? –

1

Johannes Fahrenkrug's answer bloqueó condicionalmente los gestos de panorámica incorporados de la webView. Sin embargo, descubrí que esto solo funcionaba si los gestos de panorámica de la webView eran muy lentos ... si hacía una panorámica de la vista web con cualquier velocidad razonable, el gesto de deslizamiento se activaba. Solo quería un deslizamiento rápido para activar el gesto deslizante, y paneles medianos o lentos para usar la funcionalidad de desplazamiento webView predeterminada.

El UISwipeGestureRecognizer no tiene propiedades para personalizar la velocidad de un golpe, y el UIPanGestureRecognizer tiene una propiedad de velocidad, pero no hay manera de establecer una velocidad requerida, por lo que establecer un reconocedor gesto personalizado basado en 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 

configurar sus gestos

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

Entonces detectar la dirección del gesto recibido

- (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 
     } 
    } 
} 

Tenga en cuenta que esto sólo se requiere un gesto para manejar las cuatro direcciones con banda magnética, en lugar de un UISwipeGestureRecognizer por dirección.