Snapping Collection View Layout
AppStore JSON APIs
A very interesting feature that makes the App Store fun to use is the ability to swipe between cells horizontally and watching it snap in place. Surprisingly, this isn't part of the out of the box behavior for UICollectionViewFlowLayout. Therefore we'll get our hands dirty by diving deep and creating a custom layout class that helps us achieve the snappiness of swiping.

Comments (7)
Tube
4 years ago
"Pay no attention to the man behind the curtain."
arum seo
4 years ago
the previous snappinglayout didn't have any glitch... when scrolling fast... you can notice that bettersnappinglayout will snap back to position without the smooth scrolling... did you try on a device and check? any thoughts? thanks.
Brian Voong
4 years ago
Yarduza
4 years ago
The first one works for me too.
Juanpablo Macias
3 years ago
I found this modification that takes into account the velocity as well as the bestSnappingLayout: return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) } var offsetAdjusment = CGFloat.greatestFiniteMagnitude let horizontalCenter = proposedContentOffset.x + (collectionView.bounds.width / 2) let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.bounds.size.width, height: collectionView.bounds.size.height) let layoutAttributesArray = super.layoutAttributesForElements(in: targetRect) layoutAttributesArray?.forEach({ (layoutAttributes) in let itemHorizontalCenter = layoutAttributes.center.x if abs(itemHorizontalCenter - horizontalCenter) < abs(offsetAdjusment) { if abs(velocity.x) < 0.3 { // minimum velocityX to trigger the snapping effect offsetAdjusment = itemHorizontalCenter - horizontalCenter } else if velocity.x > 0 { offsetAdjusment = itemHorizontalCenter - horizontalCenter + layoutAttributes.bounds.width } else { // velocity.x < 0 offsetAdjusment = itemHorizontalCenter - horizontalCenter - layoutAttributes.bounds.width } } }) return CGPoint(x: proposedContentOffset.x + offsetAdjusment, y: proposedContentOffset.y) }
Juanpablo Macias
3 years ago
Sorry... above was a typo: guard let collectionView = collectionView else { return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) } var offsetAdjusment = CGFloat.greatestFiniteMagnitude let horizontalCenter = proposedContentOffset.x + (collectionView.bounds.width / 2) let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.bounds.size.width, height: collectionView.bounds.size.height) let layoutAttributesArray = super.layoutAttributesForElements(in: targetRect) layoutAttributesArray?.forEach({ (layoutAttributes) in let itemHorizontalCenter = layoutAttributes.center.x if abs(itemHorizontalCenter - horizontalCenter) < abs(offsetAdjusment) { if abs(velocity.x) < 0.3 { // minimum velocityX to trigger the snapping effect offsetAdjusment = itemHorizontalCenter - horizontalCenter } else if velocity.x > 0 { offsetAdjusment = itemHorizontalCenter - horizontalCenter + layoutAttributes.bounds.width } else { // velocity.x < 0 offsetAdjusment = itemHorizontalCenter - horizontalCenter - layoutAttributes.bounds.width } } }) return CGPoint(x: proposedContentOffset.x + offsetAdjusment, y: proposedContentOffset.y) }
tsangaris
4 years ago
Turns out that this snapping effect messed up a lot of minds!! I tried to implement it on my first iOS project and i went crazy! Now i can safely cross it off my bucket list! On to the next one!
nombienombie
4 years ago
Hey Brian I noticed something odd, on the last cell in the row, it does not snap flush to the edge as it does on the preceding cells. If you take the header as an example, company name lines up perfectly with the A in Apps, but on the last cell, it does not. Do you know how to fix this please?
Brian Voong
4 years ago
Patryk Pawlak
4 years ago
I would try to set collectionView.contentInset.right to 32 (16 + 16)
jdhindsa
4 years ago
Totally lost!!!!!!!!
seventhaxis
3 years ago
Easily the most infuriating lesson in all the courses I've viewed.
jdhindsa
3 years ago
You're telling me!
jademagnum
3 years ago
Hey Brian, Can you post the link to that code for the BetterSnappingLayout?
cyuan
3 years ago
https://stackoverflow.com/a/43637969
f.ramzdev13
3 years ago
Thank god for Compositional Layout!!!
HELP & SUPPORT