2010-07-24 12 views
48

¿Hay alguna manera de saber si una celda de tabla de vista está actualmente visible? Tengo una vista de tabla cuya primera celda (0) es una uisearchbar. Si la búsqueda no está activa, oculte la celda 0 a través de un desplazamiento. Cuando la tabla solo tiene algunas filas, la fila 0 es visible. ¿Cómo determinar si la fila 0 es visible o es la fila superior?Determinar si una celda de vista de tabla está visible

Respuesta

93

UITableView tiene un método de instancia llamado indexPathsForVisibleRows que devolverá un NSArray de NSIndexPath objetos para cada fila en la tabla que están actualmente visibles. Puede verificar este método con la frecuencia que necesite y verificar la fila correcta. Por ejemplo, si tableView es una referencia a su mesa, el siguiente método podría decirle si o no la fila 0 estará en la pantalla:

-(BOOL)isRowZeroVisible { 
    NSArray *indexes = [tableView indexPathsForVisibleRows]; 
    for (NSIndexPath *index in indexes) { 
    if (index.row == 0) { 
     return YES; 
    } 
    } 

    return NO; 
} 

Debido a que el método UITableView devuelve el NSIndexPath, sólo puede extenderse fácilmente que esto busca secciones, o combinaciones de fila/sección.

Esto es más útil para usted que el método visibleCells, que devuelve una matriz de objetos de celda de tabla. Los objetos de celda de tabla se reciclan, por lo que en tablas grandes, en última instancia, no tendrán una correlación simple con su fuente de datos.

+0

gracias! fue muy útil, pero debería ser "indexPathsForVisibleRows" no "indexPathsForvisibleRows" – mklfarha

+0

Gracias por esta respuesta. Star falta. "para (índice NSIndexPath * en índices) {" –

+4

@Devunwired Tengo una pregunta de seguimiento. ¿Qué ocurre si quiero verificar si una fila ** está ** completamente visible? Su código está bien, excepto que también devuelve SÍ si la fila solo es parcialmente visible. ¡Gracias! – pixelfreak

1

IOS 4:

NSArray *cellsVisible = [tableView indexPathsForVisibleRows]; 
NSUInteger idx = NSNotFound; 
idx = [cellsVisible indexOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) 
{ 
    return ([(NSIndexPath *)obj compare:indexPath] == NSOrderedSame); 
}]; 

if (idx == NSNotFound) 
{ 
35

Para comprobar celular tableview es visible o no utilizar el código de la línea

if(![tableView.indexPathsForVisibleRows containsObject:newIndexPath]) 
    { 
     // your code 
    } 

aquí newIndexPath es IndexPath de células comprobar .....

Swift 3.0

if !(tableView.indexPathsForVisibleRows?.contains(newIndexPath)) { 
    // Your code here 

} 
+0

Obtuve su respuesta al retener el conteo en el chat gracias ... hice la misma pregunta aquí http://stackoverflow.com/questions/12990128/what-is-ios-retain-do-at-backend pero obtuve marcas negativas .. :(también, +1 para esto .. –

4

Otra solución (que también se puede usar para verificar si una fila es completamente visible) sería verificar si el marco para el row está dentro del rect visible del tableview.

En el siguiente código, ip representa la NSIndexPath:

CGRect cellFrame = [tableView rectForRowAtIndexPath:ip]; 
if (cellFrame.origin.y<tableView.contentOffset.y) { // the row is above visible rect 
    [tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO]; 
} 
else if(cellFrame.origin.y+cellFrame.size.height>tableView.contentOffset.y+tableView.frame.size.height-tableView.contentInset.top-tableView.contentInset.bottom){ // the row is below visible rect 
    [tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 
} 

También usando cellForRowAtIndexPath: debería funcionar, ya que devuelve un objeto nil si la fila no es visible:

if([tableView cellForRowAtIndexPath:ip]==nil){ 
    // row is not visible 
} 
4

Swift Version:

if let indices = tableView.indexPathsForVisibleRows { 
    for index in indices { 
     if index.row == 0 { 
      return true 
     } 
    } 
} 
return false 
7

Yo uso esto en Swift 3.0

extension UITableView { 

    /// Check if cell at the specific section and row is visible 
    /// - Parameters: 
    /// - section: an Int reprenseting a UITableView section 
    /// - row: and Int representing a UITableView row 
    /// - Returns: True if cell at section and row is visible, False otherwise 
    func isCellVisible(section:Int, row: Int) -> Bool { 
     guard let indexes = self.indexPathsForVisibleRows else { 
      return false 
     } 
     return indexes.contains {$0.section == section && $0.row == row } 
    } } 
+0

cosas fantásticas! – Fattie

0

Tenga en cuenta que "Algo visible" es "visible". Además, en vista de aparecer, es posible que obtenga falsos positivos del indexPathsForVisibleRows, ya que el diseño está en progreso, y si está mirando la última fila, incluso llamar al layoutIfNeeded() no lo ayudará con las tablas. Deberá verificar las cosas en/después del viewDidAppear.

Este código rápido de 3.1 deshabilitará el desplazamiento si la última fila es completamente visible. Llámalo in/after viewDidAppear.

let numRows = tableView.numberOfRows(inSection: 0) // this can't be in viewWillAppear because the table's frame isn't set to proper height even after layoutIfNeeded() 
    let lastRowRect = tableView.rectForRow(at: IndexPath.init(row: numRows-1, section: 0)) 
    if lastRowRect.origin.y + lastRowRect.size.height > tableView.frame.size.height { 
     tableView.isScrollEnabled = true 
    } else { 
     tableView.isScrollEnabled = false 
    } 
Cuestiones relacionadas