UICollectionView Cell Scroll to centre
you can use code
self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
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;
UPDATE: attaching Swift 4.2 version
...
collectionView.isPagingEnabled = false
...
class YourCollectionLayoutSubclass: UICollectionViewFlowLayout {
private var previousOffset: CGFloat = 0
private var currentPage: Int = 0
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView else {
return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity)
}
let itemsCount = collectionView.numberOfItems(inSection: 0)
// Imitating paging behaviour
// Check previous offset and scroll direction
if previousOffset > collectionView.contentOffset.x && velocity.x < 0 {
currentPage = max(currentPage - 1, 0)
} else if previousOffset < collectionView.contentOffset.x && velocity.x > 0 {
currentPage = min(currentPage + 1, itemsCount - 1)
}
// Update offset by using item size + spacing
let updatedOffset = (itemSize.width + minimumInteritemSpacing) * CGFloat(currentPage)
previousOffset = updatedOffset
return CGPoint(x: updatedOffset, y: proposedContentOffset.y)
}
}