2011-09-20 25 views
9

Estoy tratando de crear un UITableView con las fechas, no debería ser muy emocionante, lo sé. Comienza alrededor de la fecha actual, pero el usuario debe poder desplazarse hacia abajo (el futuro) y hacia arriba (el pasado) tanto como lo desee. Esto da como resultado un número potencialmente infinito de filas. Entonces, ¿cuál es el camino a seguir para crear esto?Desplazamiento eterno UITableView

Volviendo NSIntegerMax como el número de filas que ya se bloquea la aplicación, pero incluso si no, que todavía no tiene en cuenta por ser capaz de desplazarse hasta . Podría comenzar a mitad de camino, por supuesto, pero finalmente hay un máximo.

¿Alguna idea de cómo hacer o falsificar esto? ¿Puedo actualizar/volver a cargar la tabla de alguna manera sin que el usuario se dé cuenta, así que nunca me encuentro con un borde?

SOLUCIÓN:
Fui con la sugerencia de Ender @ e hizo una mesa con una cantidad fija de células. Pero en lugar de volver a cargarlo cuando el usuario se desplaza cerca de los bordes de las celdas fijas, fui con la recarga de la mesa cuando el desplazamiento se detiene. Para acomodar a un usuario desplazándose grandes distancias sin detenerse, acabo de aumentar el recuento de filas a 1000, poniendo la constante ROW_CENTER en 500. Este es el método que se encarga de actualizar las filas.

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    NSArray *visible = [self.tableView indexPathsForVisibleRows]; 
    NSIndexPath *upper = [visible objectAtIndex:0]; 
    NSIndexPath *lower = [visible lastObject]; 

    // adjust the table to compensate for the up- or downward scrolling 
    NSInteger upperDiff = ROW_CENTER - upper.row; 
    NSInteger lowerDiff = lower.row - ROW_CENTER; 

    // the greater difference marks the direction we need to compensate 
    NSInteger magnitude = (lowerDiff > upperDiff) ? lowerDiff : -upperDiff; 

    self.offset += magnitude; 
    CGFloat height = [self tableView:self.tableView heightForRowAtIndexPath:lower]; 
    CGPoint current = self.tableView.contentOffset; 
    current.y -= magnitude * height; 
    [self.tableView setContentOffset:current animated:NO]; 

    NSIndexPath *selection = [self.tableView indexPathForSelectedRow]; 
    [self.tableView reloadData]; 
    if (selection) 
    { 
     // reselect a prior selected cell after the reload. 
     selection = [NSIndexPath indexPathForRow:selection.row - magnitude inSection:selection.section]; 
     [self.tableView selectRowAtIndexPath:selection animated:NO scrollPosition:UITableViewScrollPositionNone]; 
    } 
} 

Se rompe la magia, cuando el usuario se desplaza hasta el borde de la mesa sin parar, pero con la vista de tabla bounces propiedad discapacitados, esto simplemente se siente como un problema menor, sin embargo, totalmente aceptable. Como siempre, ¡gracias StackOverflow!

+0

Por favor, pruebe el código en mi respuesta a continuación. Está usando una lógica simple. –

Respuesta

5

Debe establecer un número fijo de celdas y ajustar su fuente de datos cuando el usuario se desplaza cerca del final de la tabla. Por ejemplo, tiene una matriz con 51 fechas (hoy, 25 en el futuro y 25 en el pasado). Cuando la aplicación intenta hacer que una celda cerca de una de las fronteras, volver a configurar la matriz y llamar reloadData

+0

Gracias por la sugerencia. Estoy intentando esto ahora, pero llamar a reloadData no ajustará la posición de desplazamiento (o contentOffset) de la vista de tabla, por lo que deja de desplazarse. ¿Cuál fue tu idea sobre eso? Aclamaciones. – epologee

+0

Me temo que no hay forma de volver a cargar datos sin detener el desplazamiento. Tal vez estableciendo manualmente el contentOffset de la tabla de la celda actual después de llamar a reloadData ... – ender

+0

Escogí la solución, pero puse la recarga en el método 'scrollViewDidEndDecelerating:'. De esta forma, el usuario no notará la recarga. Al aumentar el recuento de filas a un número alto plausible (como 1000) se hará cargo de la mayoría de los casos de uso sin notar fallas. ¡Gracias! – epologee

2

Dos pensamientos:

  1. lo que realmente necesita un UITableView? Puede usar un UIScrollView, tres pantallas altas. Si se llega al final del desplazamiento, diseñe su contenido y ajuste la posición de desplazamiento. Esto da la ilusión de desplazamiento infinito. Crear algunas etiquetas de fecha y organizarlas en layoutSubviews: no debería ser demasiado esfuerzo.

  2. Si realmente quiere seguir con UITableView, podría pensar en tener dos UITableViews. Si desplazarse en el primero llega a un punto crítico, desenchufe un hilo y rellene el segundo. Luego, en algún momento, intercambie las vistas y active el desplazamiento manualmente para que el usuario no note el cambio. Esto es solo una idea desde lo más alto de mi cabeza. Todavía no he implementado algo como esto, pero implementé el infinito UIScrollView.

+0

Buenas sugerencias. He estado reflexionando sobre el primero yo mismo, pero quería apegarme al UITableView debido a toda la reutilización de la celda y al hecho de que se siente como debería ser una mesa: S. Voy a probar el UIScrollVer uno para ver qué tan bien se mantiene. ¡Gracias! – epologee

3

También puede echar un vistazo a la charla "Scroll Avanzada Ver Técnicas" de la WWDC 2011. Ellos mostraron cómo se crearía un UIScrollView la que se desplaza de forma indefinida. Comienza a unos 5 minutos. en.

+0

Gracias, buen consejo, tengo ese buffer en alguna parte. ¡Ah, y muchas gracias por Trazzle man, lo usó durante años! – epologee

0

que respondieron a esta pregunta en otro post: https://stackoverflow.com/a/15305937/2030823

incluyen:

https://github.com/samvermette/SVPullToRefresh

SVPullToRefresh maneja la lógica cuando UITableView llega al fondo. Se muestra una rueda giratoria automáticamente y se dispara un bloque de devolución de llamada. Agregas tu lógica de negocios al bloque de devolución de llamada.

#import "UIScrollView+SVInfiniteScrolling.h" 

// ... 

[tableView addInfiniteScrollingWithActionHandler:^{ 
    // append data to data source, insert new cells at the end of table view 
    // call [tableView.infiniteScrollingView stopAnimating] when done 
}]; 
0

Esta pregunta ya ha sido pedido: implementing a cyclic UITableView estoy copiando esa respuesta aquí para que sea más fácil debido a que el autor de la pregunta no ha marcado mi respuesta.

UITableView es igual que UIScrollView en el método scrollViewDidScroll.

Por lo tanto, es fácil emular el desplazamiento infinito.

  1. el doble de la matriz de modo que la cabeza y la cola se unen entre sí para emular mesa circular

  2. usar mi siguiente código para hacer cambio de usuario entre la primera parte de la tabla duplicado y segunda parte de la tabla duplicado cuando tienden para llegar al comienzo o al final de la mesa.

:

/* To emulate infinite scrolling... 

The table data was doubled to join the head and tail: (suppose table had 1,2,3,4) 
1 2 3 4|1 2 3 4 (actual data doubled) 
--------------- 
1 2 3 4 5 6 7 8 (visualizing joined table in eight parts) 

When the user scrolls backwards to 1/8th of the joined table, user is actually at the 1/4th of actual data, so we scroll instantly (we take user) to the 5/8th of the joined table where the cells are exactly the same. 

Similarly, when user scrolls to 6/8th of the table, we will scroll back to 2/8th where the cells are same. (I'm using 6/8th when 7/8th sound more logical because 6/8th is good for small tables.) 

In simple words, when user reaches 1/4th of the first half of table, we scroll to 1/4th of the second half, when he reaches 2/4th of the second half of table, we scroll to the 2/4 of first half. This is done simply by subtracting OR adding half the length of the new/joined table. 

Written and posted by Anup Kattel. Feel free to use this code. Please keep these comments if you don't mind. 
*/ 


-(void)scrollViewDidScroll:(UIScrollView *)scrollView_ 
{ 

    CGFloat currentOffsetX = scrollView_.contentOffset.x; 
    CGFloat currentOffSetY = scrollView_.contentOffset.y; 
    CGFloat contentHeight = scrollView_.contentSize.height; 

    if (currentOffSetY < (contentHeight/8.0)) { 
    scrollView_.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY + (contentHeight/2))); 
    } 
    if (currentOffSetY > ((contentHeight * 6)/ 8.0)) { 
     scrollView_.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY - (contentHeight/2))); 
    } 

} 

P. S. - He usado este código en una de mis aplicaciones llamada NT Time Table (Lite). Si desea obtener la vista previa, puede consultar la aplicación: https://itunes.apple.com/au/app/nt-time-table-lite/id528213278?mt=8

Si su tabla a veces puede ser demasiado corta, al comienzo del método anterior puede agregar una lógica if para salir cuando el conteo de datos es, por ejemplo, menos de 9.

Cuestiones relacionadas