2011-02-28 12 views

Respuesta

17

La mejor manera es poner a prueba un punto en la parte inferior de la pantalla y usar esta llamada al método, cuando cada vez el usuario se desplaza (scrollViewDidScroll):

- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point 

prueba un punto cerca de la parte inferior de la pantalla, y luego, al usar indexPath, se devuelve la comprobación de si indexPath es la última fila y, si es así, se agregan filas.

+0

Desafortunadamente, mi Ap p actualizará los datos en tiempo real para las filas existentes en esta tabla, de esta manera puede obtener más contenido cuando la tabla no sea scroll. –

13

UITableView es una subclase de UIScrollView, y UITableViewDelegate corresponde a UIScrollViewDelegate. Por lo tanto, el delegado que adjunte a la vista de tabla obtendrá eventos como scrollViewDidScroll:, y puede llamar a métodos como contentOffset en la vista de tabla para encontrar la posición de desplazamiento.

+0

Sí, esto es lo que estoy buscando, implemente ese delegado y compruebe si la posición de desplazamiento es UITableViewScrollPositionBottom, sabré cuándo la tabla se desplaza hacia abajo, muchas gracias –

243

en el delegado tableview hacer algo como esto

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView { 
    CGPoint offset = aScrollView.contentOffset; 
    CGRect bounds = aScrollView.bounds; 
    CGSize size = aScrollView.contentSize; 
    UIEdgeInsets inset = aScrollView.contentInset; 
    float y = offset.y + bounds.size.height - inset.bottom; 
    float h = size.height; 
    // NSLog(@"offset: %f", offset.y); 
    // NSLog(@"content.height: %f", size.height); 
    // NSLog(@"bounds.height: %f", bounds.size.height); 
    // NSLog(@"inset.top: %f", inset.top); 
    // NSLog(@"inset.bottom: %f", inset.bottom); 
    // NSLog(@"pos: %f of %f", y, h); 

    float reload_distance = 10; 
    if(y > h + reload_distance) { 
     NSLog(@"load more rows"); 
    } 
} 
+2

Publicación muy útil. Aclamaciones. – Echilon

+0

¡Muy útil! Gracias por evitarme hacer las matemáticas. – Johnny

+0

¿Por qué no es esta la respuesta elegida? –

18

Ninguna de las respuestas anteriores me ayudó, así que se le ocurrió esto:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView 
{ 
    NSArray *visibleRows = [self.tableView visibleCells]; 
    UITableViewCell *lastVisibleCell = [visibleRows lastObject]; 
    NSIndexPath *path = [self.tableView indexPathForCell:lastVisibleCell]; 
    if(path.section == lastSection && path.row == lastRow) 
    { 
     // Do something here 
    } 
} 
+0

¿Puede explicar de dónde viene "lastSection"? – ainesophaur

+0

esto es para la vista de desplazamiento y no la tabla – iosMentalist

38

añadir este método en el UITableViewDelegate:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    CGFloat height = scrollView.frame.size.height; 

    CGFloat contentYoffset = scrollView.contentOffset.y; 

    CGFloat distanceFromBottom = scrollView.contentSize.height - contentYoffset; 

    if(distanceFromBottom < height) 
    { 
     NSLog(@"end of the table"); 
    } 
} 
+3

Me gusta esta solución, excepto un pequeño detalle. if (distanceFromBottom <= height) –

+0

Esto me ayudó a solucionar mi problema, gracias !! una barra de pestañas !! ¡fue una barra de pestañas estúpida! – Dmytro

+0

esto funciona como un amuleto, y también es simple, pero estoy enfrentando un pequeño problema como que se está ejecutando dos o tres veces en la última fila. ¿Cómo hacer que se ejecute solo una vez cuando alcanza la última fila de la vista de tabla? –

19

Uso – tableView:willDisplayCell:forRowAtIndexPath: (método UITableViewDelegate)

Simplemente compare el indexPath con los elementos en su conjunto de datos (o cualquier fuente de datos que utilice para su vista de tabla) para averiguar si se visualiza el último elemento.

Docs: http://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:willDisplayCell:forRowAtIndexPath:

+0

Luego, si recarga los datos de tableView ', estará atrapado en un ciclo infinito. –

59

neoneyes modificados responden un poco.

Esta respuesta se dirige a aquellos de ustedes que solo quieren que el evento se desencadene una vez por liberación del dedo.

Adecuado para cargar más contenido de algún proveedor de contenido (servicio web, datos básicos, etc.). Tenga en cuenta que este enfoque no respeta el tiempo de respuesta de su servicio web.

- (void)scrollViewDidEndDragging:(UIScrollView *)aScrollView 
        willDecelerate:(BOOL)decelerate 
{ 
    CGPoint offset = aScrollView.contentOffset; 
    CGRect bounds = aScrollView.bounds; 
    CGSize size = aScrollView.contentSize; 
    UIEdgeInsets inset = aScrollView.contentInset; 
    float y = offset.y + bounds.size.height - inset.bottom; 
    float h = size.height; 

    float reload_distance = 50; 
    if(y > h + reload_distance) { 
     NSLog(@"load more rows"); 
    } 
} 
+4

awesome work @eyeball ... tu respuesta es la perfecta ... al menos en mi punto de vista. – harshitgupta

+0

Esto no funciona. Cada vez que el usuario se desplaza hacia abajo, se llama a "cargar más filas". Esto sucede incluso cuando el usuario ya se ha desplazado hacia abajo y está esperando que la API devuelva datos. – Dean

+2

Dean, la pregunta era sobre saber cuándo la vista de tabla se desplazó hacia abajo. Ya sea que esté buscando datos de una API o no, es irrelevante, ¿o no? – Eyeball

7
NSLog(@"%f/%f",tableView.contentOffset.y, tableView.contentSize.height - tableView.frame.size.height); 

if (tableView.contentOffset.y == tableView.contentSize.height - tableView.frame.size.height) 
     [self doSomething]; 

agradable y sencillo de

2

que quieren realizar alguna acción en mi Cualquiera 1 Tableviewcell completa.

Así que el código es enlazar el:

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    NSArray* cells = self.tableView.visibleCells; 
    NSIndexPath *indexPath = nil ; 

    for (int aIntCount = 0; aIntCount < [cells count]; aIntCount++) 
    { 

     UITableViewCell *cell = [cells objectAtIndex:aIntCount]; 
CGRect cellRect = [self.tableView convertRect:cell.frame toView:self.tableView.superview]; 

     if (CGRectContainsRect(self.tableView.frame, cellRect)) 
     { 
      indexPath = [self.tableView indexPathForCell:cell]; 

    // remain logic 
     } 
    } 
} 

de mayo de este es ayuda a alguien.

5

general Lo utilizo para cargar más datos, cuando la última célula comienza pantalla

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (indexPath.row == myDataArray.count-1) { 
     NSLog(@"load more"); 
    } 
} 
+1

esto está mal. Cada vez que llame a reloadData se realizará una solicitud. Y a veces solo necesitas volver a cargar la tabla. –

+0

que quería decir, si está en la última celda y luego hizo una recarga de datos, ¿entonces sucederá? –

3

Mi solución es añadir células antes tableview se desacelerará en estima a compensar. Es predecible por velocidad.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)offset { 

    NSLog(@"offset: %f", offset->y+scrollView.frame.size.height); 
    NSLog(@"Scroll view content size: %f", scrollView.contentSize.height); 

    if (offset->y+scrollView.frame.size.height > scrollView.contentSize.height - 300) { 
     NSLog(@"Load new rows when reaches 300px before end of content"); 
     [[DataManager shared] fetchRecordsNextPage]; 
    } 
} 
+0

funciona bien :-) –

7

en Swift puedes hacer algo como esto. Siguiente condición será verdad cada vez que alcance final de la tableview

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
     if indexPath.row+1 == postArray.count { 
      println("came to last row") 
     } 
} 
+0

el problema es cuando TableView tiene solo 3 celdas, por ejemplo, 'println (" llegó a la última fila ")' ¡se ejecuta este código! –

5

Sobre la base de la respuesta de @Jay Mayu, me pareció que era una de las mejores soluciones:

Objective-C

// UITableViewDelegate 
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { 

// Need to call the service & update the array 
if(indexPath.row + 1 == self.sourceArray.count) { 
    DLog(@"Displayed the last row!"); 
    } 
} 

2.x Swift

// UITableViewDelegate 
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    if (indexPath.row + 1) == sourceArray.count { 
     print("Displayed the last row!") 
    } 
} 
5

Tomando neoneye excelentes respuestas, pero en Swift, y el cambio de nombre de las variables ..

Básicamente sabemos que hemos llegado a la parte inferior de la vista de tabla si el yOffsetAtBottom está más allá de la altura contenido de la tabla.

func isTableViewScrolledToBottom() -> Bool { 
    let tableHeight = tableView.bounds.size.height 
    let contentHeight = tableView.contentSize.height 
    let insetHeight = tableView.contentInset.bottom 

    let yOffset = tableView.contentOffset.y 
    let yOffsetAtBottom = yOffset + tableHeight - insetHeight 

    return yOffsetAtBottom > contentHeight 
} 
5

Aquí está el código rápido de la versión 3.0.

func scrollViewDidScroll(_ scrollView: UIScrollView) { 

     let offset = scrollView.contentOffset 
     let bounds = scrollView.bounds 
     let size = scrollView.contentSize 
     let inset = scrollView.contentInset 
     let y: Float = Float(offset.y) + Float(bounds.size.height) + Float(inset.bottom) 
     let height: Float = Float(size.height) 
     let distance: Float = 10 

     if y > height + distance { 
      // load more data 
     } 
    } 
3

Actualización para Swift 3

respuesta de Neoneye funcionó mejor para mí en Objective C, esto es el equivalente a la respuesta en Swift 3:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { 
    let offset: CGPoint = scrollView.contentOffset 
    let bounds: CGRect = scrollView.bounds 
    let size: CGSize = scrollView.contentSize 
    let inset: UIEdgeInsets = scrollView.contentInset 
    let y: CGFloat = offset.y + bounds.size.height - inset.bottom 
    let h: CGFloat = size.height 
//  print("offset: %f", offset.y) 
//  print("content.height: %f", size.height) 
//  print("bounds.height: %f", bounds.size.height) 
//  print("inset.top: %f", inset.top) 
//  print("inset.bottom: %f", inset.bottom) 
//  print("position: %f of %f", y, h) 

    let reloadDistance: CGFloat = 10 

    if (y > h + reloadDistance) { 
      print("load more rows") 
    } 
} 
Cuestiones relacionadas