objective c - Combinando un UILongPressGestureRecognizer con un UIPanGestureRecognizer
objective-c cocoa-touch (5)
Me gustaría combinar un UILongPressGestureRecognizer con un UIPanGestureRecognizer.
El UIPanGestureRecognizer debe comenzar con una pulsación larga. ¿Hay una manera simple de hacer esto? ¿O realmente tengo que escribir mi propio reconocedor de gestos?
No quiero algo como en la pantalla de inicio. Presionas un icono y después de un tiempo los iconos comienzan a tambalearse. Luego, sin soltar mi dedo de la pantalla, puedo comenzar a arrastrar el icono debajo de mi dedo.
El enfoque de Andy B en Swift,
Agregue el delegado UIGestureRecognizerDelegate a la clase
class ViewController: UIViewController, UIGestureRecognizerDelegate
Añadir una variable miembro
var shouldAllowPan: Bool = false
Agregue los gestos y necesita agregar el delegado de gesto de paneo a la VC. Esto es necesario para disparar las funciones shouldRecognizeSimultaneouslyWithGestureRecognizer y el gestoRecognizerShouldBegin
// long press let longPressRec = UILongPressGestureRecognizer(target: self, action: "longPress:") yourView.addGestureRecognizer(longPressRec) // drag let panRec = UIPanGestureRecognizer(target: self, action: "draggedView:") panRec.delegate = self yourView.addGestureRecognizer(panRec)
Permitir gestos simultáneos.
func gestureRecognizer(UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool { // println("shouldRecognizeSimultaneouslyWithGestureRecognizer"); return true } func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool { // We only allow the (drag) gesture to continue if it is within a long press if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) { return false; } return true; }
Dentro del manejador de prensa larga:
func longPress(sender: UILongPressGestureRecognizer) { if(sender.state == .Began) { // handle the long press } else if(sender.state == .Changed){ shouldAllowPan = true } else if (sender.state == .Ended) { shouldAllowPan = false } }
Encontré una solución: este método UIGestureRecognizerDelegate hace exactamente lo que buscaba:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Lea la sección "Notas de subclasificación" de la referencia de clase UIGestureRecognizer de Apple en:
Tuve un poco de dificultad para este problema. La respuesta aceptada no fue suficiente. No importa lo que ponga en ese método, se invocarían los controladores pan o longpress. Una solución que encontré fue la siguiente:
- Asegúrese de que los delegados de los reconocedores de gestos estén asignados a la misma clase (en mi caso, yo mismo) y de que la clase delegada sea un
UIGestureRecognizerDelegate
. Agregue el siguiente método de delegado a su clase (según la respuesta anterior):
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; }
Agregue el siguiente método de delegado a su clase:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) { return NO; } return YES; }
Luego, agregue una propiedad o ivar que rastreará si se debe permitir que comience la bandeja (consulte el método anterior). En mi caso
BOOL shouldAllowPan
.Establezca BOOL en
NO
en suinit
oviewDidLoad
. Dentro de su controlador longPress, establezca BOOL enYES
. Lo hago así:- (void) longPressHandler: (UILongPressGestureRecognizer *) gesture { if(UIGestureRecognizerStateBegan == gesture.state) { shouldAllowPan = NO; } if(UIGestureRecognizerStateChanged == gesture.state) { shouldAllowPan = YES; } }
Dentro de panHandler hago un chequeo en el BOOL:
- (void)panHandler:(UIPanGestureRecognizer *)sender{ if(shouldAllowPan) { // do your stuff }
Y finalmente reinicie el BOOL dentro de panHandler:
else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) { shouldAllowPan = NO; }
Y luego ir a tomar una cerveza para felicitarte. ;)
en realidad, no tiene que combinar reconocedores de gestos; puede hacer esto únicamente con UILongPressGestureRecognizer ... Usted ingresa a StateBegan una vez que sus toques se han mantenido dentro de ''permisible de movimiento'' para ''minimumPressDuration''. Permanece en tu continuo PressGesture siempre y cuando no levantes ninguno de tus dedos, para que puedas comenzar a moverlos y seguir el movimiento a través de StateChanged.
Los gestos de larga pulsación son continuos. El gesto comienza (UIGestureRecognizerStateBegan) cuando se presiona el número de dedos permitidos (numberOfTouchesRequired) durante el período especificado (minimumPressDuration) y los toques no se mueven más allá del rango de movimiento permitido (permisible). El reconocedor de gestos pasa al estado de cambio cada vez que se mueve un dedo y finaliza (UIGestureRecognizerStateEnded) cuando se levanta cualquiera de los dedos.