¿UIGestureRecognizer funciona en un UIWebView?

Estoy intentando obtener un UIGestureRecognizer que funcione con una UIWebview que es una subvista de UIScrollView. Esto suena extraño, pero cuando tengo el número de numberOfTouchesRequired configurado en 2, el selector se dispara, pero cuando numberOfTouchesRequired se establece en uno, el selector no se dispara.

Aquí está mi código:

 UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(select1:)]; tap1.numberOfTouchesRequired = 2; tap1.numberOfTapsRequired = 1; tap1.delegate = self; [self.ans1WebView addGestureRecognizer:tap1]; [tap1 release]; - (void) select1:(UILongPressGestureRecognizer *)sender { //Do Stuff } 

Lo he confirmado al usar la muestra de Apple para UIGestureRecognizer e insertar una vista web en su plumilla. Su código de tap funciona en todas partes pero dentro del área de la vista web.

Por lo que he visto, UIWebView no funciona bien con otros. Para los reconocedores de gestos, podría intentar devolver SÍ desde:

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; 

Tenía que ser compatible con versiones anteriores de 3.0, así que terminé haciendo todo el manejo de gestos con Javascript dentro de UIWebView. No es una buena solución, pero funcionó para mis necesidades. Pude capturar una pulsación larga en un elemento, así como tocar, deslizar, pellizcar y girar. Por supuesto, estaba usando solo contenido local.

Editar:

Puede buscar en PhoneGap un ejemplo de envío de mensajes al delegado de UIWebView. En pocas palabras, utiliza document.location = "myscheme:mycommand?myarguments" luego analiza el comando y los argumentos de esta callback delegada:

 -(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType { if ( [[[inRequest URL] absoluteString] hasPrefix:@"myscheme:"] ) { //.. parse arguments return NO; } } 

Puede ver en el código PhoneGap que configuraron una cola y un temporizador para enviar los mensajes. Dependiendo de su uso, es posible que deba hacer lo mismo. Hay otras preguntas sobre SO sobre este tema.

Aquí está la documentación de manejo de eventos . En mi caso, agregué detectores de eventos para document desde

 function myloader() { document.addEventListener( 'touchcancel' , touch_cancel , false ); document.addEventListener( 'touchstart' , touch_start , false ); document.addEventListener( 'touchmove' , touch_move , false ); document.addEventListener( 'touchend' , touch_end , false ); }; 

El manejo real del evento depende mucho de sus necesidades. Cada controlador de eventos recibirá un TouchEvent con una propiedad de toques donde cada elemento es un Touch . Puede registrar la hora y la ubicación de inicio en su controlador Touchstart. Si los toques se mueven demasiado o pasa la cantidad de tiempo incorrecta, no es un toque prolongado.

WebKit puede tratar de manejar un toque largo para comenzar una selección y copia. En su controlador de eventos puede usar event.preventDefault(); para detener el comportamiento predeterminado También encontré la -webkit-user-select:none css a la mano para algunas cosas.

 var touch = {}; function touch_start( event /*TouchEvent*/ { event.preventDefault(); touch = {}; touch.startX = event.touches.item(0).pageX; touch.startY = event.touches.item(0).pageY; touch.startT = ( new Date() ).getTime(); } 

Este es solo el segundo proyecto con el que he usado javascript. Puedes encontrar mejores ejemplos en otros lugares.

Como puede ver, esta no es una respuesta rápida a su problema. Estoy muy contento con los resultados que obtuve. El html con el que estaba trabajando no tenía elementos interactivos más allá de uno o dos enlaces.

UIWebView tiene sus propias vistas privadas, que también tienen reconocedores de gestos adjuntos. Por lo tanto, las reglas de precedencia evitan que cualquier reconocedor de gestos agregado a UIWebView funcione correctamente.

Una opción es implementar el protocolo UIGestureRecognizerDelegate e implementar el método gestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer. Regrese SÍ de este método para otros gestos de toque. De esta forma, se llamará a su controlador de acceso y la vista web seguirá recibiendo su llamada.

Mira esto en los foros de desarrollo de Apple .

Esta es una solución algo pirateada, pero funciona. UIWebView tiene muchos reconocedores de gestos internos a los que normalmente no se puede acceder sin utilizar una API privada. Sin embargo, los obtienes todos gratis cuando implementas gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: En ese punto, puede indicar a todos los UITAPGestureRecognizers internos que se activen solo cuando su propio UITAPGestureRecognizer haya fallado. Solo lo hace una vez y luego elimina el delegado de su propio reconocedor de gestos. El resultado es que aún puede desplazarse y desplazarse por su vista web, pero ya no recibirá ningún gesto de toque (único).

 - (void)viewDidLoad { [super viewDidLoad]; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; // view is your UIViewController's view that contains your UIWebView as a subview [self.view addGestureRecognizer:tap]; tap.delegate = self; } - (void)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { NSLog(@"tap!"); // this is called after gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: so we can safely remove the delegate here if (gestureRecognizer.delegate) { NSLog(@"Removing delegate..."); gestureRecognizer.delegate = nil; } } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { if ([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) { [otherGestureRecognizer requireGestureRecognizerToFail:gestureRecognizer]; NSLog(@"added failure requirement to: %@", otherGestureRecognizer); } return YES; } 

¡Disfrutar!

Estaba teniendo el mismo problema. Esta solución funcionó para mí:

1) Asegúrese de agregar el protocolo a su interfaz: UIGestureRecognizerDelegate por ejemplo:

 @interface ViewController : UIViewController  

2) Agregue esta línea de código

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES } 

3) Gesto de configuración

 UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(nextSlide)]; swipeGesture.numberOfTouchesRequired = 1; swipeGesture.direction = (UISwipeGestureRecognizerDirectionLeft); swipeGesture.cancelsTouchesInView = YES; [swipeGesture setDelegate:self]; [self.view addGestureRecognizer:swipeGesture]; 
 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer { return YES; } 

Otra forma es colocar un UIButton transparente encima de UIWebView y manejar los toques desde este botón. En algunos casos, podría ser una buena solución.

 UIWebView webView = [UIWebView new]; //... UIButton *transparentButton = [UIButton buttonWithType:UIButtonTypeCustom]; [transparentButton addTarget:self action:@selector(buttonTapped) forControlEvents:(UIControlEventTouchUpInside)]; transparentButton.frame = webView.frame; transparentButton.layer.backgroundColor = [[UIColor clearColor] CGColor]; [self.view transparentButton]; 

También puede encontrar mi respuesta aquí útil. Es un ejemplo práctico de cómo manejar el gesto de pellizco en javascript de UIWebView.

(Podrías comunicar los eventos al Objective-C si quisieras. Mira mi respuesta aquí ).