2012-04-05 18 views
7

En el momento en que recibo touchesBegan, quiero removeFromSuperview la vista que se tocó y addSuperview a una nueva vista principal, y luego continúo para recibir toques. Sin embargo, estoy descubriendo que a veces esto no funciona. Específicamente, touchesMoved y touchesEnded nunca se llaman.iOS: ¿Transferir la propiedad de UIView mientras ocurren los toques?

¿Hay algún truco para hacer que esto funcione correctamente? Esto es para implementar un comportamiento de arrastrar y soltar, donde la vista se encuentra inicialmente dentro de una vista de desplazamiento.

Gracias.

Respuesta

0

Necesita procesar sus toques en la supervista en lugar de en la vista que desea cambiar. Esto le permitirá cambiar la vista sin perder sus eventos táctiles. Sin embargo, cuando hagas esto, deberás probar si el toque se está produciendo en la subvista específica que deseas cambiar. Esto se puede hacer de muchas maneras, pero aquí hay algunos métodos para empezar:

conversión de Rect/punto a otro punto de vista:

[view convertRect:rect toView:subview]; 
[view convertPoint:point toView:subview]; 

Éstos son algunos métodos para probar si el punto se encuentra en la vista :

[subView hitTest:point withEvent:nil]; 
CGRectContainsPoint(subview.frame, point); //No point conversion needed 
[subView pointInside:point withEvent:nil]; 

En general, es mejor usar UIGestureRecognizers. Por ejemplo, si estuviera usando un UIPanGestureRecognizer, crearía un método que el reconocedor de gestos puede invocar y en ese método hará su trabajo. Por ejemplo:

- (void) viewPanned:(UIPanGestureRecognizer *)pan{ 
    if (pan.state == UIGestureRecognizerStateBegan){ 
     CGRect rect = subView.frame; 
     newView = [[UIView alloc] initWithFrame:rect]; 
     [subView removeFromSuperview]; 
     [self addSubview:newView]; 
    } else if (pan.state == UIGestureRecognizerStateChanged){ 
     CGPoint point = [pan locationInView:self]; 
     newView.center = point; 
    } else { 
     //Do cleanup or final view placement 
    } 
} 

Entonces init el reconocedor, asigna al objetivo (por lo general uno mismo) y añadirlo:

[self addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewPanned:)]]; 

Ahora sí (que sería el supervista gestión es subvistas) responderá para mover los movimientos

+0

No estoy seguro de por qué sería eso. ¿Puedes publicar el código? Por cierto, ¿qué le impide usar un UIGestureRecognizer? En casi todos los casos que he considerado usar Touches, he encontrado que un UIGestureRecognizer existente o una subclasificación de UIGestureRecognizer funciona mejor (y puedo reutilizarlo). –

+0

Si está utilizando el stock UIPanGestureRecognizer, 'touchesBegan' no debe estar en su código. Debería configurar algún método de destino como este: '- (void) viewPanned: (UIPanGestureRecognizer) pan'. Cuando inicia el reconocedor, establece su objetivo: '[[UIPanGestureRecognizer alloc] initWithTarget: self action: @selector (viewPanned :)]'.Se llamará repetidamente a este método y podrá verificar el estado y realizar las acciones apropiadas: 'If (pan.state == UIGestureRecognizerStateBegan) {.......}' o 'If (pan.state == UIGestureRecognizerStateChanged {. ....} 'etc ... –

+0

Expandí mi respuesta para reflejar esto. –

7

En lugar de:

[transferView removeFromSuperView]; 
[newParentView addSubview:transferView]; 

solamente Uso:

[newParentView addSubview:transferView]; 

Dentro de la documentación se afirma "Las vistas pueden tener sólo un supervista Si la vista ya tiene un supervista y que. view no es el receptor, este método elimina la supervista anterior antes de convertir al receptor en su nueva supervista ".

Por lo tanto, no es necesario utilizar removeFromSuperView porque es manejado por addSubview. Me he dado cuenta de que removeFromSuperView finaliza los toques actuales sin llamar a toquesEnded. Si usa solo addSubview, los toques no se interrumpen.

+1

Esta debería ser la respuesta aceptada, ya que no es necesario administrar el arrastre en la supervista para lograr el objetivo del OP. Simplemente eliminando ** removeFromSuperView ** hace el truco. Gracias ** walapu **. – walkingbrad

+0

¡Gran respuesta, esto fue muy útil! – Max

Cuestiones relacionadas