¿Es posible personalizar el reconocimiento de gestos deslizable que activa el desplazamiento UIScrollView?

He creado una subclass personalizada desde UIScrollView e implementado los touchesBegan touchesMoved , touchesEnded touchesBegan , touchesMoved touchesEnded y touchesCancelled methods de touchesCancelled .

Sin embargo, no estoy satisfecho con cómo funcionan las cosas. Particularmente, cuando se mencionan los methods recibidos y cuando UIScrollView decide desplazarse (arrastrar).

UIScrollView desplaza incluso si la diferencia entre el primer punto de contacto y el último punto de contacto es muy poca en dirección vertical. Entonces puedo deslizar casi horizontalmente y UIScrollView se desplazará hacia arriba o hacia abajo dependiendo de esa pequeña diferencia (que está perfectamente bien en los casos de uso normal)

Comportamiento predeterminado de UIScrollView

Ambos movimientos podrían hacer que UIScrollView desplace hacia abajo.

Sin embargo, me interesa que sea posible ajustarlo de alguna manera, para que se comporte así:

Comportamiento deseado

Básicamente para que el touchesBegan horizontal cercano sea recogido por touchesBegan y methods relacionados y no inicie el desplazamiento. Sin embargo, la dirección de desplazamiento verde todavía iniciaría el desplazamiento …

EDITAR:

Olvidé mencionar, touchesBegan y sus familiares reciben llamadas si mantienes el dedo por un corto período de time en la pantalla y luego lo mueves. Entonces, no es un gesto clásico de deslizar …

Ivan, creo que estás tratando de hacer el mismo efecto que la página de Facebook, y arrastra la vista de desplazamiento, así que dejando que la vista de desplazamiento siga tu dedo, si eso es correcto, sugiero que te olvides de tocar events y comiences con UIPanGesture, es el mejor en estos casos, por lo que dentro del delegado que llama a ese gesto, coloque el siguiente código para ello:

  //The sender view, in your case the scollview UIScrollView* scr = (UIScrollView*)sender.view; //Disable the scrolling flag for the sake of user experience [scr setScrollEnabled:false]; //Get the current translation point of the scrollview in respect to the main view CGPoint translation = [sender translationInView:self.view]; //Set the view center to the new translation point float translationPoint = scr.center.x + translation.x; scr.center = CGPointMake(translationPoint,scr.center.y); [sender setTranslation:CGPointMake(0, 0) inView:self.view]; 

Christopher Nassar correctamente señaló que debería utilizar UIPanGestureRecognizer , así que experimenté un poco con él.

Lo que descubrí es que si agrega un UIPanGestureRecognizer a la supervisión que contiene su UIScrollView . ¡Entonces el UIScrollView incorporado en el reconocimiento de gestos de pan va a funcionar en pareja con su propio UIPanGestureRecognizer de la manera exacta que deseaba!

El UIPanGestureRecognizer los golpes horizontales y casi horizontales de la UIPanGestureRecognizer de supervisión y todos los demás verticales mediante el reconocedor UIScrollView (personalizado) incorporado en el reconocimiento de gestos y hará que se desplace …

Supongo que UIScrollView se diseñó de esta manera, ya que el comportamiento pnetworkingeterminado sería que solo uno de estos reconocedores de gestos panorámicos dispara, o ambos simultáneamente si UIScrollView devuelve SÍ desde este método UIPanGestureRecognizerDelegate :

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

Sin embargo, parece que UIScrollView tiene lógica adicional para deshabilitar selectivamente (para desplazamientos horizontales) su propio reconocedor de desplazamiento en caso de que exista otro.

Tal vez alguien aquí sabe más detalles al respecto.

Así que, para resumir, la solución para mí fue agregar un UIPanGestureRecognizer dentro de viewDidLoad en mi UIViewController . (Nota: UIScrollView se agrega como una subvista a esa vista de UIViewController )

 UIPanGestureRecognizer *myPanGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [self.view addGestureRecognizer:myPanGestureRecognizer]; 

y luego agregue el método del controller:

 - (void)handlePan:(UIPanGestureRecognizer *)recognizer { NSLog(@"Swiped horizontally..."); }