最好的方法来检查UITableViewCell是否完全可见

我有一个UITableView与不同高度的细胞,我需要知道什么时候他们是完全可见或不。

此刻,我正在遍历可见单元格列表中的每个单元格,以检查每次滚动视图时是否完全可见。 这是最好的办法吗?

这是我的代码:

- (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]; } } } 

编辑:

请注意* – (NSArray )visibleCells返回可见的单元格,它们都是完全可见的,部分可见的。

编辑2:

这是lnafzigerVadim Yelagin合并解决scheme后的修改后的代码:

 - (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]; } 

我会像这样改变它:

 - (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]; } 

你可以用rectForRowAtIndexPath:方法得到一个单元格的矩形,并使用CGRectContainsRect函数将它与tableview的边界矩形进行CGRectContainsRect

请注意,如果单元格不可见,则不会实例化该单元格,因此会相当快速。

迅速

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

OBJ-C

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

当然,这不会将表视图视为超视图剪切或被另一视图遮挡。

你可以尝试这样的事情,看看有多less百分比是可见的:

 -(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]; } } } } 

从文档:

visibleCells返回接收器中可见的表格单元格。

- (NSArray *)visibleCells

返回值包含UITableViewCell对象的数组,每个对象表示接收表视图中的可见单元格。

Availability在iOS 2.0及更高版本可用。

另请参阅 – indexPathsForVisibleRows

 - (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 } 

即使您说每次滚动时都要检查一下,也可以使用

 -(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 } }