iphone - Cómo robar toques de UIScrollView?
ios4 nested (3)
A veces tienes que hacer la pregunta antes de poder encontrar la respuesta. Dan Ray tuvo un problema similar y lo resolvió con una solución muy diferente.
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
if ([result.superview isKindOfClass:[UIPickerView class]])
{
self.scrollEnabled = NO;
}
else
{
self.scrollEnabled = YES;
}
return result;
}
He probado el código y también funciona bien para mí. Sin embargo, esto no está robando toques de la vista de desplazamiento, por lo que si alguien sabe cómo robar toques realmente sería genial.
Fuente: UIPickerView dentro de UITableView.tableFooterView no recibe toques de arrastre
Hoy, en mi tiempo creativo, realicé algunas investigaciones exhaustivas sobre cómo robar toques de un UIScrollView y enviarlos instantáneamente a una subvista específica, mientras mantengo el comportamiento predeterminado para el resto de la vista de desplazamiento. Considere tener un UIPickerView dentro de una UITableView. El comportamiento predeterminado es que si arrastra su dedo sobre la vista del selector, la vista de desplazamiento se desplazará y la vista del selector permanecerá sin cambios.
Lo primero que intenté fue anular
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
y simplemente no permitir que UIScrollView cancele los toques dentro de la vista del selector. Esto funciona, pero tiene un efecto secundario desagradable. Desea que la vista del selector responda de inmediato y, por lo tanto, deberá establecer delaysContentTouches
en NO. El problema es que no desea que el resto de la vista de tabla responda de inmediato, porque si lo hace, la celda de la vista de tabla siempre se resaltará durante unos pocos milisegundos antes de que comience el desplazamiento.
Lo segundo que intenté fue anular
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
porque había leído que la vista de desplazamiento siempre se devuelve a sí misma, de modo que "robará" los toques de sus subvistas y luego los enviará a la subvista si no fueran de interés para la vista de desplazamiento. Sin embargo, esto ya no es verdad. Implementación predeterminada de UIScrollView de hitTest: withEvent: en realidad devuelve la subvista que debería recibir el toque. En cambio, usa reconocedores de gestos para interceptar los toques.
Entonces, lo tercero que intenté fue implementar mi propio reconocedor de gestos y hacer que fallara si el toque estaba fuera de la vista del selector y de lo contrario tendría éxito. Luego configuré todos los reconocedores de gestos de la vista de desplazamiento para que fallaran, a menos que mi reconocedor de gestos fallara con el siguiente código:
for (UIGestureRecognizer * gestureRecognizer in self.tableView.gestureRecognizers)
{
[gestureRecognizer requireGestureRecognizerToFail:myRecognizer];
}
Esto de hecho roba los toques de la vista de desplazamiento, pero la vista del selector nunca los recibe. Así que pensé que tal vez podría enviar todos los toques que mi reconocedor de gestos recibe usando este código:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches)
[touch.view touchesBegan:touches withEvent:event];
}
El código anterior es una versión simplificada. También me aseguro de que la vista sea una vista de selector (o una de sus subvistas) y establezco el estado apropiado para el reconocedor de gestos como mencioné anteriormente. También hice lo mismo para cancelar, finalizar y moverme. Sin embargo, la vista del selector aún no respondía.
También intenté una última cosa antes de regresar a mi trabajo habitual. Durante mi extensa búsqueda en Google, leí que UIScrollViews anidados funcionaba mágicamente desde 3.x, así que traté de poner mi vista de selector dentro de UIScrollView anidado y establecí las siguientes propiedades en él:
scrollView.delaysContentTouches = NO;
scrollView.canCancelContentTouches = NO;
Como era de esperar que la vista de desplazamiento externo no tratara la vista de desplazamiento interior de forma diferente a la vista del selector, por lo que la vista de desplazamiento interior no recibió los toques. Pensé que era una posibilidad remota, pero fue lo suficientemente simple de implementar, así que pensé que valía la pena intentarlo.
Lo que sé es que UIScrollView tiene un reconocedor de gestos llamado UIScrollViewDelayedTouchesBeganGestureRecognizer
que intercepta los toques y los envía a la subvista apropiada después de 150 (?) Ms. Estoy pensando que debería poder escribir un reconocedor similar que haga que los reconocedores predeterminados de la vista de desplazamiento fallen y, en lugar de demorar los toques, los envíe inmediatamente a la vista del selector. Entonces, si alguien sabe cómo escribir un reconocedor, por favor avíseme y si tiene otra solución al problema, puede compartirlo también.
Gracias por leer toda la pregunta e incluso si no sabes la respuesta, aún puedes votar la pregunta para que reciba más atención (esperemos que de alguien que pueda responderla). ¡Gracias! :)
También llego tarde a la fiesta, pero para los recién llegados, si solo quieres ignorar los deslizamientos en la vista de desplazamiento, lo que funcionó para mí fue agregar un reconocedor de movimiento de pan a la vista que quiero ignorar los golpes, como esta:
let panGesture = UIPanGestureRecognizer()
panGesture.cancelsTouchesInView = false
myView?.addGestureRecognizer(panGesture)
Un poco tarde, pero encontré esta solución: http://www.cocoanetics.com/2010/06/hacking-uiscrollview-gesture-recognizers/ Funciona para mí