2010-08-06 13 views
26

Básicamente, aquí está mi vista de jerarquía (y yo appologize si esto es difícil de leer ... Soy nuevo aquí lo que la publicación sugerencias felizmente aceptadas)toques de Desactivar el fondo UIView modo que los botones de vistas inferiores se puede hacer clic


--AppControls.xib
------- (UIView) ControlsView
----------------- (UIView) topbar
--- -------------- -------------- btn1, btn2, btn3
--------------- - UIView) BottomBar
----------------- - ------------- slider1 btn1, btn2
--PageContent.xib
----------------- (UIView) ContentView
- ---------------- -------------- btn1, btn2, btn3
------------- ---- -------------- (UIImageView) FullPageImage


Mi situación es que quiero para ocultar y mostrar los controles al tocar cualquier parte de la PageContent eso no es una y muestran los controles, al igual que el reproductor de video de iPhone. Sin embargo, cuando se muestran los controles, todavía quiero poder hacer clic en los botones del contenido de la página.

Tengo todo esto funcionando, excepto el último bit. Cuando los controles muestran el fondo de los controles, recibe los eventos táctiles en lugar de la vista a continuación. Y al desactivar la interacción del usuario en el ControlsView, se desactiva en todos sus elementos secundarios.

He intentado anular HitTest en mi subclase ControlsView de la siguiente que encontré en un puesto similar:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ 
UIView *hitView = nil; 
NSArray *subviews = [self subviews]; 
int subviewCount = [subviews count]; 
for (int subviewIndex = 0; !hitView && subviewIndex < subviewCount; subviewIndex++){ 
hitView = [[subviews objectAtIndex:subviewIndex] hitTest:point withEvent:event]; 
} 
return hitView; 
} 

Sin embargo, en este punto de mi control deslizante no funciona, ni la mayoría de los otros botones, y realmente, las cosas empiezan a ponerse raras.

Así que mi pregunta es en resumen: ¿Cómo dejo que todas las subvistas de una vista tengan eventos táctiles, mientras que el fondo de la supervista no se puede cliquear, y los botones en las vistas a continuación pueden recibir eventos táctiles?

Gracias!

Respuesta

60

Estás cerca. No anule -hitTest:withEvent:. En el momento en que se invoca, el despachador de eventos ya ha decidido que su subárbol de la jerarquía posee el evento y no buscará en otro lado. En cambio, anule -pointInside:withEvent:, que se llama anteriormente en la canalización de procesamiento de eventos. Es como el sistema pregunta "hey view, ¿ALGUIEN en su jerarquía responde a un evento en este punto?". Si dice NO, el procesamiento de eventos continúa debajo de usted en la pila visible.

Según el documentation, la implementación predeterminada simplemente verifica si el punto está dentro de los límites de la vista.

Su estrategia es decir "sí" cuando cualquiera de sus subvistas está en esa coordenada, pero diga "no" cuando el toque toque el fondo.

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    for (UIView * view in [self subviews]) { 
     if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) { 
      return YES; 
     } 
    } 
    return NO; 
} 
+1

perfecto! Muchas gracias! – averydev

+1

De nada. Luché con este mismo problema durante muchas horas una vez. Feliz de ayudar. –

+0

Por cierto, ¿es esa una manera más o menos propicia para graficar la jerarquía de visualización? ¿O hay una práctica estándar? – averydev

1

Otro enfoque puede ser tener un botón invisible de pantalla completa detrás de todo lo demás, y tomar las medidas adecuadas cuando se golpea.

+0

Eso suena como una idea terrible. –

1

Una pequeña variante en la respuesta de Ben, que trata con niños que se extiende fuera de su padre. Si clipChildren es SÍ, entonces esto no devolverá SÍ a puntos que están fuera del control principal pero dentro de algún elemento secundario. if clipChildren es NO, esto es lo mismo que Ben's.

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    BOOL clipChildren = YES; 

    if (!clipChildren || [super pointInside:point withEvent:event]) { 
     for (UIView * view in [self subviews]) { 
      if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) { 
       return YES; 
      } 
     } 
    } 
    return NO; 
} 
2

Gracias a @Ben Zutto, 3 Swift solución:

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 
    for view in self.subviews { 
     if view.isUserInteractionEnabled, view.point(inside: self.convert(point, to: view), with: event) { 
      return true 
     } 
    } 

    return false 
} 
Cuestiones relacionadas