objective-c - framework - uikit ios
Detectar panoramización horizontal en UITableView (5)
¡Gracias por los consejos! Eventualmente elegí una subclase UITableView, donde verifico si el movimiento es horizontal (en cuyo caso uso mi comportamiento personalizado), y si no, llamo a [super touchesMoved: withEvent:] ;.
Sin embargo, todavía no entiendo por qué funciona esto. Lo revisé, y super es un UITableView. Parece que aún no entiendo completamente cómo funciona esta jerarquía. ¿Alguien puede intentar y explicar?
Estoy usando un UIPanGestureRecognizer para reconocer deslizamiento horizontal en una UITableView (en una celda para ser preciso, aunque se agrega a la tabla). Sin embargo, este reconocedor de gestos obviamente roba los toques de la mesa. Ya obtuve el reconocimiento de pangestura para reconocer el deslizamiento horizontal y luego ajustarlo a eso; pero si el usuario comienza deslizando verticalmente, debe pasar todos los eventos desde ese toque hasta la vista de tabla.
Una cosa que he intentado fue deshabilitar el reconocedor, pero luego no se desplazaría hasta el siguiente evento táctil. Entonces lo necesitaría para pasar el evento de inmediato.
Otra cosa que probé fue hacer que se enrollara, pero luego perderá la velocidad persistente después de detener el toque.
Aquí hay un código:
//In the viewdidload method
UIPanGestureRecognizer *slideRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(sliding:)];
[myTable addGestureRecognizer:slideRecognizer];
-(void)sliding:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan)
{
CGPoint translation = [recognizer translationInView:favoritesTable];
if (sqrt(translation.x*translation.x)/sqrt(translation.y*translation.y)>1) {
horizontalScrolling = YES; //BOOL declared in the header file
NSLog(@"horizontal");
//And some code to determine what cell is being scrolled:
CGPoint slideLocation = [recognizer locationInView:myTable];
slidingCell = [myTable indexPathForRowAtPoint:slideLocation];
if (slidingCell.row == 0) {
slidingCell = nil;
}
}
else
{
NSLog(@"cancel");
}
if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled)
{
horizontalScrolling = NO;
}
if (horizontalScrolling)
{
//Perform some code
}
else
{
//Maybe pass the touch from here; It''s panning vertically
}
}
Entonces, ¿algún consejo sobre cómo pasar los toques?
Además: también pensé que tal vez subclases el método reconocedor de gestos de la tabla, para verificar primero si es horizontal; Sin embargo, entonces necesitaría el código original, supongo ... No tengo idea de si Apple tendrá problemas con él. Además: no subclasé el UITableView (controlador), solo las celdas. Este código está en viewcontroller que contiene la tabla;)
¿Tal vez puedas usar UISwipeGestureRecognizer
en UISwipeGestureRecognizer
lugar? Puedes decirle que ignore los deslizamientos arriba / abajo a través de la propiedad de direction
.
Puede intentar usar los eventos táctiles manualmente en lugar de los reconocedores de gestos. Siempre pasando el evento de vuelta a la vista de tabla, excepto cuando finalmente reconoce el gesto deslizar.
Cada clase que hereda de UIResponder tendrá las cuatro funciones táctiles (comenzada, finalizada, cancelada y movida). Así que la forma más sencilla de "reenviar" una llamada es manejarla en su clase y luego llamarla explícitamente al próximo objeto que desee manejar (pero debe asegurarse de verificar si el objeto responde al mensaje primero con respondsToSelector: ya que es una función opcional). De esta forma, puede detectar cualquier evento que desee y también permitir la interacción táctil normal con cualquier otro elemento que lo necesite.
Tuve el mismo problema y se me ocurrió una solución que funciona con UIPanGestureRecognizer.
A diferencia de Erik, agregué el UIPanGestureRecognizer directamente a la celda, ya que solo necesito una celda en particular para apoyar la panorámica. Pero supongo que esto debería funcionar también para el caso de Erik.
Aquí está el código.
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
UIView *cell = [gestureRecognizer view];
CGPoint translation = [gestureRecognizer translationInView:[cell superview]];
// Check for horizontal gesture
if (fabsf(translation.x) > fabsf(translation.y))
{
return YES;
}
return NO;
}
El cálculo para el gesto horizontal se copia del código de Erik; lo he probado con iOS 4.3.
Editar: descubrí que esta implementación impide el gesto de "deslizar para eliminar". Para recuperar ese comportamiento, he agregado la verificación de la velocidad del gesto a la instrucción if anterior.
if ([gestureRecognizer velocityInView:cell].x < 600 && sqrt(translate...
Después de jugar un poco en mi dispositivo, se me ocurrió una velocidad de 500 a 600, que ofrece en mi opinión la mejor experiencia de usuario para la transición entre la panorámica y el gesto de deslizar para borrar.
Mi respuesta es la misma que la de Florian Mielke, pero la he simplificado y corregido.
Cómo utilizar:
Simplemente dele a su UIPanGestureRecognizer
un delegado ( UIGestureRecognizerDelegate
). Por ejemplo:
UIPanGestureRecognizer *panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDetected:)];
panner.delegate = self;
[self addGestureRecognizer:panner];
Luego haga que ese delegado implemente el siguiente método:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
CGPoint translation = [(UIPanGestureRecognizer *)gestureRecognizer translationInView:gestureRecognizer.view.superview];
return fabsf(translation.x) > fabsf(translation.y);
}