Skip to content

Instantly share code, notes, and snippets.

@jklp
Created July 29, 2014 06:30
Show Gist options
  • Save jklp/7d4201e3d9801ba78945 to your computer and use it in GitHub Desktop.
Save jklp/7d4201e3d9801ba78945 to your computer and use it in GitHub Desktop.
Snaps UICollectionViewCell to center when cell isn't entire width of screen
//
// Code based on http://markuzweb.blogspot.com.au/2014/02/uicollectionview-paging-for-smaller-width-cells.html
//
// Note, need to create property called "previousXoffset" in class and doesn't need to be
// initialized by default
//
- (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, and only allowing user
// to scroll either 1 cell left or right (can't scroll more tha 2 cells)
int indexOfItemToSnap = round(self.previousXoffset / visibleWidth);
if (self.previousXoffset < point.x) {
indexOfItemToSnap++;
} else {
indexOfItemToSnap--;
}
// The only exemption is the last item.
CGFloat xOffset;
if (indexOfItemToSnap + 1 == [self.collectionView numberOfItemsInSection:0]) { // last item
xOffset = self.collectionView.contentSize.width - self.collectionView.bounds.size.width;
} else {
xOffset = indexOfItemToSnap * visibleWidth;
}
self.previousXoffset = xOffset;
*targetContentOffset = CGPointMake(xOffset, 0);
}
@vikdenic
Copy link

Tried implementing this in Swift and no luck; notice anything off in my translation to Swift?

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    let point = targetContentOffset.pointee

    let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

    let visibleWidth = layout.minimumInteritemSpacing + layout.itemSize.width

    var indexOfItemToSnap = round(self.previousXoffset / visibleWidth)

    if previousXoffset < point.x {
        indexOfItemToSnap += 1
    } else {
        indexOfItemToSnap -= 1
    }

    var xOffset = CGFloat()
    if indexOfItemToSnap + 1 == CGFloat(collectionView.numberOfItems(inSection: 0)) {
        xOffset = CGFloat(collectionView.contentSize.width - collectionView.bounds.size.width)
    } else {
        xOffset = indexOfItemToSnap * visibleWidth
    }
    previousXoffset = xOffset
    targetContentOffset.pointee = CGPoint(x: xOffset, y: 0)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment