Nitya Nitya - 14 days ago 8
iOS Question

UICollectionView Cell Scroll to centre

I am using UICollectionView in my UIViewController.

My collectionview properties are set as below.

enter image description here

Now I would like cell to be Centre on screen after scroll!
Option 1:

enter image description here

Option 2:
enter image description here

What would I have to do achieve option 2?

UPDATE:

In the end I have used following code as scrolling with other answer is not smooth.

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{ CGFloat offsetAdjustment = MAXFLOAT;
CGFloat horizontalCenter = proposedContentOffset.x + (CGRectGetWidth(self.collectionView.bounds) / 2.0);

CGRect targetRect = CGRectMake(proposedContentOffset.x, 0.0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
NSArray* array = [super layoutAttributesForElementsInRect:targetRect];

for (UICollectionViewLayoutAttributes* layoutAttributes in array) {
CGFloat itemHorizontalCenter = layoutAttributes.center.x;

if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offsetAdjustment)) {
offsetAdjustment = itemHorizontalCenter - horizontalCenter;
}
}
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}

Answer

You can override targetContentOffsetForProposedContentOffset:withScrollingVelocity: method in your UICollectionViewLayout subclass and calculate your offset there like this:

@property (nonatomic, assign) CGFloat previousOffset;
@property (nonatomic, assign) NSInteger currentPage;

...

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
    NSInteger itemsCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];

    // Imitating paging behaviour
    // Check previous offset and scroll direction
    if ((self.previousOffset > self.collectionView.contentOffset.x) && (velocity.x < 0.0f)) {
        self.currentPage = MAX(self.currentPage - 1, 0);
    } else if ((self.previousOffset < self.collectionView.contentOffset.x) && (velocity.x > 0.0f)) {
        self.currentPage = MIN(self.currentPage + 1, itemsCount - 1);
    }

    // Update offset by using item size + spacing
    CGFloat updatedOffset = (self.itemSize.width + self.minimumInteritemSpacing) * self.currentPage;
    self.previousOffset = updatedOffset;

    return CGPointMake(updatedOffset, proposedContentOffset.y);
}

EDIT: thanks for pointing this out, forgot to say that you have to disable paging first:

self.collectionView.pagingEnabled = NO;