In the application I'm working on, there's a 320pt wide horizontal-only scrolling UICollectionView with varied content width depending on the number of items. The UICollectionViewCell subclass or itemView being used here has a width of 250pt enough to let the next itemView peak just a little bit. And I need to show one itemView at a time by snapping to the closest one.
// NOTE: This delegate method requires you to disable UICollectionView's `pagingEnabled` property. - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { CGPoint point = *targetContentOffset; UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout; // This assumes that the values of `layout.sectionInset.left` and // `layout.sectionInset.right` are the same with `layout.minimumInteritemSpacing`. // Remember that we're trying to snap to one item at a time. So one // visible item comprises of its width plus the left margin. CGFloat visibleWidth = layout.minimumInteritemSpacing + layout.itemSize.width; // It's either we go forwards or backwards. int indexOfItemToSnap = round(point.x / visibleWidth); // The only exemption is the last item. if (indexOfItemToSnap + 1 == [self.collectionView numberOfItemsInSection:0]) { // last item *targetContentOffset = CGPointMake(self.collectionView.contentSize.width - self.collectionView.bounds.size.width, 0); } else { *targetContentOffset = CGPointMake(indexOfItemToSnap * visibleWidth, 0); } }