pods library eureka custom best ios uitableview visible

ios - library - La mejor forma de comprobar si UITableViewCell es completamente visible



swift libraries (10)

Tengo una UITableView con celdas de diferentes alturas y necesito saber cuándo son completamente visibles o no.

En este momento estoy recorriendo cada celda en la lista de celdas visibles para verificar si está completamente visible cada vez que se desplaza la vista. ¿Es este el mejor enfoque?

Aquí está mi código:

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView { CGPoint offset = aScrollView.contentOffset; CGRect bounds = aScrollView.bounds; NSArray* cells = myTableView.visibleCells; for (MyCustomUITableViewCell* cell in cells) { if (cell.frame.origin.y > offset.y && cell.frame.origin.y + cell.frame.size.height < offset.y + bounds.size.height) { [cell notifyCompletelyVisible]; } else { [cell notifyNotCompletelyVisible]; } } }

Editar:

Tenga en cuenta que * - (NSArray ) visibleCells devuelve celdas visibles que son completamente visibles y parcialmente visibles.

Editar 2:

Este es el código revisado después de combinar las soluciones de ambos, lnafziger y Vadim Yelagin :

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView { NSArray* cells = myTableView.visibleCells; NSArray* indexPaths = myTableView.indexPathsForVisibleRows; NSUInteger cellCount = [cells count]; if (cellCount == 0) return; // Check the visibility of the first cell [self checkVisibilityOfCell:[cells objectAtIndex:0] forIndexPath:[indexPaths objectAtIndex:0]]; if (cellCount == 1) return; // Check the visibility of the last cell [self checkVisibilityOfCell:[cells lastObject] forIndexPath:[indexPaths lastObject]]; if (cellCount == 2) return; // All of the rest of the cells are visible: Loop through the 2nd through n-1 cells for (NSUInteger i = 1; i < cellCount - 1; i++) [[cells objectAtIndex:i] notifyCellVisibleWithIsCompletelyVisible:YES]; } - (void)checkVisibilityOfCell:(MultiQuestionTableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { CGRect cellRect = [myTableView rectForRowAtIndexPath:indexPath]; cellRect = [myTableView convertRect:cellRect toView:myTableView.superview]; BOOL completelyVisible = CGRectContainsRect(myTableView.frame, cellRect); [cell notifyCellVisibleWithIsCompletelyVisible:completelyVisible]; }


De los documentos:

visibleCells Devuelve las celdas de la tabla que están visibles en el receptor.

- (NSArray *)visibleCells

Valor de retorno Una matriz que contiene objetos UITableViewCell, cada uno representa una celda visible en la vista de tabla de recepción.

Disponibilidad Disponible en iOS 2.0 y posterior.

Ver también - indexPathsForVisibleRows


El siguiente código le permitirá verificar si una celda de vista de colección es completamente visible a través de los atributos de diseño de la vista de colección.

guard let cellRect = collectionView.layoutAttributesForItem(at: indexPath)?.frame else { return } let isCellCompletelyVisible = collectionView.bounds.contains(cellRect)


Incluso si dijera que desea verificarlo cada vez que se desplazó, también puede usar

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { CGRect cellRect = [tableView convertRect:cell.frame toView:tableView.superview]; if (CGRectContainsRect(tableView.frame, cellRect)){ //Do things in case cell is fully displayed } }


Puede obtener el rect de una celda con el método rectForRowAtIndexPath: y compararlo con los límites de tableview rect usando la función CGRectContainsRect .

Tenga en cuenta que esto no creará una instancia de la celda si no está visible, y por lo tanto será bastante rápido.

Rápido

let cellRect = tableView.rectForRowAtIndexPath(indexPath) let completelyVisible = tableView.bounds.contains(cellRect)

Obj-C

CGRect cellRect = [tableView rectForRowAtIndexPath:indexPath]; BOOL completelyVisible = CGRectContainsRect(tableView.bounds, cellRect);

Por supuesto, esto no tendrá en cuenta que la vista de tabla sea recortada por una supervista u oscurecida por otra vista.


Puedes probar algo como esto para ver cuánto porcentaje es visible:

-(void)scrollViewDidScroll:(UIScrollView *)sender { [self checkWhichVideoToEnable]; } -(void)checkWhichVideoToEnable { for(UITableViewCell *cell in [tblMessages visibleCells]) { if([cell isKindOfClass:[VideoMessageCell class]]) { NSIndexPath *indexPath = [tblMessages indexPathForCell:cell]; CGRect cellRect = [tblMessages rectForRowAtIndexPath:indexPath]; UIView *superview = tblMessages.superview; CGRect convertedRect=[tblMessages convertRect:cellRect toView:superview]; CGRect intersect = CGRectIntersection(tblMessages.frame, convertedRect); float visibleHeight = CGRectGetHeight(intersect); if(visibleHeight>VIDEO_CELL_SIZE*0.6) // only if 60% of the cell is visible { // unmute the video if we can see at least half of the cell [((VideoMessageCell*)cell) muteVideo:!btnMuteVideos.selected]; } else { // mute the other video cells that are not visible [((VideoMessageCell*)cell) muteVideo:YES]; } } } }


Si también desea tener en cuenta el contentInset y no desea confiar en una supervista (el marco de la vista de tabla en superview podría ser algo más que 0,0), esta es mi solución:

extension UITableView { public var boundsWithoutInset: CGRect { var boundsWithoutInset = bounds boundsWithoutInset.origin.y += contentInset.top boundsWithoutInset.size.height -= contentInset.top + contentInset.bottom return boundsWithoutInset } public func isRowCompletelyVisible(at indexPath: IndexPath) -> Bool { let rect = rectForRow(at: indexPath) return boundsWithoutInset.contains(rect) } }


Tal vez para este tema utilice mejor la función siguiente de UITableViewDelegate

func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath)


Yo lo cambiaría así:

- (void)checkVisibilityOfCell:(MyCustomUITableViewCell *)cell inScrollView:(UIScrollView *)aScrollView { CGRect cellRect = [aScrollView convertRect:cell.frame toView:aScrollView.superview]; if (CGRectContainsRect(aScrollView.frame, cellRect)) [cell notifyCompletelyVisible]; else [cell notifyNotCompletelyVisible]; } - (void)scrollViewDidScroll:(UIScrollView *)aScrollView { NSArray* cells = myTableView.visibleCells; NSUInteger cellCount = [cells count]; if (cellCount == 0) return; // Check the visibility of the first cell [self checkVisibilityOfCell:[cells firstObject] inScrollView:aScrollView]; if (cellCount == 1) return; // Check the visibility of the last cell [self checkVisibilityOfCell:[cells lastObject] inScrollView:aScrollView]; if (cellCount == 2) return; // All of the rest of the cells are visible: Loop through the 2nd through n-1 cells for (NSUInteger i = 1; i < cellCount - 1; i++) [[cells objectAtIndex:i] notifyCompletelyVisible]; }


- (BOOL)checkVisibilityOfCell{ if (tableView.contentSize.height <= tableView.frame.size.height) { return YES; } else{ return NO; } }


UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath]; CGRect frame = cell.frame; if (CGRectContainsRect(CGRectOffset(self.collectionView.frame, self.collectionView.contentOffset.x, self.collectionView.contentOffset.y), frame)) { // is on screen }