Kind of like evya's answer, but a little smoother because it doesn't set the targetContentOffset to zero.
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
if ([scrollView isKindOfClass:[UICollectionView class]]) {
UICollectionView* collectionView = (UICollectionView*)scrollView;
if ([collectionView.collectionViewLayout isKindOfClass:[UICollectionViewFlowLayout class]]) {
UICollectionViewFlowLayout* layout = (UICollectionViewFlowLayout*)collectionView.collectionViewLayout;
CGFloat pageWidth = layout.itemSize.width + layout.minimumInteritemSpacing;
CGFloat usualSideOverhang = (scrollView.bounds.size.width - pageWidth)/2.0;
// k*pageWidth - usualSideOverhang = contentOffset for page at index k if k >= 1, 0 if k = 0
// -> (contentOffset + usualSideOverhang)/pageWidth = k at page stops
NSInteger targetPage = 0;
CGFloat currentOffsetInPages = (scrollView.contentOffset.x + usualSideOverhang)/pageWidth;
targetPage = velocity.x < 0 ? floor(currentOffsetInPages) : ceil(currentOffsetInPages);
targetPage = MAX(0,MIN(self.projects.count - 1,targetPage));
*targetContentOffset = CGPointMake(MAX(targetPage*pageWidth - usualSideOverhang,0), 0);
}
}
}