101 votes

Meilleur moyen de vérifier si UITableViewCell est complètement visible

J'ai un UITableView avec les cellules de différentes hauteurs et j'ai besoin de savoir quand ils sont complètement visibles ou non.

Pour le moment, je suis en parcourant chaque cellule de la liste de cellules visibles pour vérifier si il est complètement visible à chaque fois que l'affichage défile à l'écran . Est-ce la meilleure approche?

Voici mon code:

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

Edit:

Veuillez noter que *- (NSArray )visibleCells retourne cellules visibles qui sont à la fois complètement visible et en partie visible.

Edit 2:

C'est le code révisé après la combinaison de solutions à partir de deux lnafziger et 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];
}

134voto

Vadim Yelagin Points 785

Vous pouvez obtenir le rect d'une cellule avec rectForRowAtIndexPath: méthode, de les convertir en table superview coordonnées avec convertRect:toView: méthode (pour annuler la vitesse de défilement) et de le comparer avec tableview du cadre rect l'aide d' CGRectContainsRect fonction.

Notez que ce ne sera pas instancier la cellule si elle n'est pas visible, et donc sera assez rapide.

L'ensemble du code est quelque chose de ce genre (pas testé):

CGRect cellRect = [tableView rectForRowAtIndexPath:indexPath];
cellRect = [tableView convertRect:cellRect toView:tableView.superview];
BOOL completelyVisible = CGRectContainsRect(tableView.frame, cellRect);

Bien sûr, cela n'a égard à la vue de la table d'être accroché par un superview ou caché par un autre point de vue.

65voto

lnafziger Points 18241

Je le changerais comme ça:

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

5voto

CodaFi Points 29073

De la docs:

visibleCells Renvoie les cellules de tableau visibles dans le récepteur.

- (NSArray *)visibleCells

Valeur de retour Un tableau contenant des objets UITableViewCell, chacun représentant une cellule visible dans la vue de table réceptrice.

Disponibilité Disponible dans iOS 2.0 et versions ultérieures.

Voir aussi - indexPathsForVisibleRows

0voto

Andy Poes Points 406
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
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X