I know some people have asked this question before but they were all about UITableViews
or UIScrollViews
and I couldn't get the accepted solution to work for me. What I would like is the snapping effect when scrolling through my UICollectionView
horizontally - much like what happens in the iOS AppStore. iOS 9+ is my target build so please look at the UIKit changes before answering this.
Thanks.
Got an answer from SO post here and docs here
First What you can do is set your collection view's scrollview's delegate your class by making your class a scrollview delegate
Then make set your view controller as the delegate
Or do it in the interface builder by control + shift clicking on your collection view and then control + drag or right click drag to your view controller and select delegate. (You should know how to do this). That doesn't work. UICollectionView is a subclass of UIScrollView so you will now be able to see it in the interface builder by control + shift clicking
Next implement the delegate method
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
The docs state that:
Then inside of that method check which cell was closest to the center of the scrollview when it stopped scrolling
This from a 2012 WWDC video for an Objective-C solution. I subclassed UICollectionViewFlowLayout and added the following.
And the reason I got to this question was for the snapping with a native feel, which I got from Mark's accepted answer... this I put in the collectionView's view controller.
Based on answer from Mete and comment from Chris Chute,
Here's a Swift 4 extension that will do just what OP wants. It's tested on single row and double row nested collection views and it works just fine.
You need to implement
UIScrollViewDelegate
protocol for your collection view and then add these two methods:If you want simple native behavior, without customization:
This only works properly when the size of the collection view layout items are all one size only and the
UICollectionViewCell
'sclipToBounds
property is set toYES
.Snap to the nearest cell, respecting scroll velocity.
Works without any glitches.
I just found what I think is the best possible solution to this problem:
First add a target to the collectionView's already existing gestureRecognizer:
Have the selector point to a method which takes a UIPanGestureRecognizer as a parameter:
Then in this method, force the collectionView to scroll to the appropriate cell when the pan gesture has ended. I did this by getting the visible items from the collection view and determining which item I want to scroll to depending on the direction of the pan.
Keep in mind that in my case only two items can be visible at a time. I'm sure this method can be adapted for more items however.