UICollectionView current visible cell index

Irfan DANISH picture Irfan DANISH · Sep 6, 2013 · Viewed 146.7k times · Source

I am using UICollectionView first time in my iPad application. I have set UICollectionView such that its size and cell size is same, means only once cell is displayed at a time.

Problem: Now when user scroll UICollectionView I need to know which cell is visible I have to update other UI elements on change. I didn't find any delegate method for this. How can I achieve this?

Code:

[self.mainImageCollection setTag:MAIN_IMAGE_COLLECTION_VIEW];
[self.mainImageCollection registerClass:[InspirationMainImageCollectionCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
[self.mainImageFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.mainImageFlowLayout setMinimumInteritemSpacing:0.0f];
[self.mainImageFlowLayout setMinimumLineSpacing:0.0f];
self.mainImageFlowLayout.minimumLineSpacing = 0;
[self.mainImageCollection setPagingEnabled:YES];
[self.mainImageCollection setShowsHorizontalScrollIndicator:NO];
[self.mainImageCollection setCollectionViewLayout:self.mainImageFlowLayout];

What I have tried:

As UICollectionView conforms to UIScrollView, I got when user scroll ends with UIScrollViewDelegate method

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

But inside above function how can I get current visible cell index of UICollectionView ?

Answer

lobianco picture lobianco · Jun 24, 2014

indexPathsForVisibleItems might work for most situations, but sometimes it returns an array with more than one index path and it can be tricky figuring out the one you want. In those situations, you can do something like this:

CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];

This works especially well when each item in your collection view takes up the whole screen.

Swift version

let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
let visibleIndexPath = collectionView.indexPathForItem(at: visiblePoint)