2011-06-15 12 views
16

Tengo un montón de UIViews como en la imagen a continuación. La vista roja/rosa (semitransparente) está encima de las otras.¿Cómo encontrar confiablemente la vista correcta para UIGestureRecognizer?

  • Rojo tiene UISwipeGestureRecognizer.
  • Verde tiene como UITapGestureRecognizer.
  • Azul no tiene reconocedor.

enter image description here

Un toque en la parte visible (inferior izquierda) de gatillo verde su reconocedor.

Un golpecito en las ocultos partes del verde no gatillo de su reconocedor (Rojas bloquea).

Ese es el problema: quiero que se dispare Green. ¿Cómo puedo hacer esto?

En la práctica, las vistas pueden estar en cualquier orden, cualquier número y ser subvistas de los demás, etc. Pero el problema es el mismo:

¿Cómo puedo encontrar de forma fiable la vista superior que puede manejar el gesto (toque o deslice)?


He intentado con el siguiente código. Atraviesa prolijamente todas las vistas, pero falla, ya que no puede saber si el evento es parte de un deslizamiento o un toque. Entonces el método siempre devuelve la vista roja. Si elimino el reconocedor de deslizamiento de Rojo, el código funciona correctamente.

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    UIView *hitView = [super hitTest:point withEvent:event]; 
    if (hitView == self) 
    { 
     if (self.hasASwipeRecognizer) 
      return self; // What if this was a tap? 
     if (self.hasATapRecognizer) 
      return self; 
     else 
      return nil; 
    } 
    else 
     return hitView; 
} 

Respuesta

16

Una alternativa para agregar el reconocedor de gestos a estas vistas sería agregar los reconocedores de gestos a la vista principal y manejar los casos de uso de forma apropiada utilizando el método delegado gestureRecognizer:shouldReceiveTouch: método.

Identifique si el reconocedor particular debe recibir el toque y devuelva YES. Por ejemplo, si el reconocedor de gestos aprobado es un reconocedor de barrido, compruebe si el punto de contacto está dentro de la vista verde y devuelva YES. Devuelva NO de lo contrario.

Si hay reconocedores de gestos similares, entonces sugiero que guarde una referencia y verifique en contra de ello.

Uso

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { 
    CGPoint pointInView = [touch locationInView:gestureRecognizer.view]; 

    if ([gestureRecognizer isMemberOfClass:[UITapGestureRecognizer class]] 
     && CGRectContainsPoint(self.blueView.frame, pointInView)) { 
     return YES; 
    } 

    if ([gestureRecognizer isMemberOfClass:[UISwipeGestureRecognizer class]] 
     && CGRectContainsPoint(self.greenView.frame, pointInView)) { 
     return YES; 
    } 

    return NO; 
} 
+0

Sí, la clave para esto es (como usted dice) para agregar todos los reconocedores a la supervista y manejarlo desde allí. Mi jerarquía es arbitrariamente compleja (creo que sopa de polígono) pero esta idea funciona. –

3

Una posible solución sería añadir un reconocedor del grifo gesto a la vista superior rojo y luego cada vez que reciba el grifo, comprobar si el punto de derivación se cruza con la vista verde. Si es así, reenvía el grifo a esa vista. Si no, ignora el toque.

3

Mis soluciones es:

-(void)handleGesture:(UIGestureRecognizer*)gestureRecognizer { 
    CGPoint touchPoint = [tapGestureRecognizer locationInView:viewUnderTest]; 
    if ([viewUnderTest pointInside:touchPoint withEvent:nil]) { 
     NSLog(@"Hit done in view under test"); 
    } 
} 
Cuestiones relacionadas