iphone - tapgesture recognizer swift
Swipe Gesture Recognition Inside UIWebView (3)
Sí, puede decirle al UIScrollView de UIWebView que su UIPanGestureRecognizer solo debe activarse cuando su UISwipeGestureRecognizer ha fallado.
Así es como lo haces:
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];
Eso debería hacer el truco para ti.
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 de UIWebView
, siempre que no haya 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 manera de diferenciar entre "deslizar" y simplemente desplazarse con el dedo (no levantarlo sino arrastrarlo para desplazarse).
Deberá subclasificar UIWebView y anular las llamadas de reconocimiento de gestos.
EDITAR - Mira esta publicación Manejo de toques dentro de UIWebview y este enlace http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/
La respuesta de Johannes Fahrenkrug tuvo éxito al bloquear condicionalmente los gestos de panoramización integrados 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 deslizamiento, y UIPanGestureRecognizer tiene una propiedad de velocidad, pero no hay manera de establecer una velocidad requerida, así que configuré un reconocedor de gestos personalizado basado en este 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
Configura tus gestos
FastSwipeGestureRecognizer *swipeGesture = [[FastSwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)];
[self.view addGestureRecognizer:swipeGesture];
[self.webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeGesture];
Luego detecta 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 solo requiere un gesto para manejar las cuatro direcciones de deslizamiento, en lugar de un UISwipeGestureRecognizer por dirección.