I'm using a UICollectionView
to scroll through a set of thumbnails quickly. Once scrolling ends, I'd like to display a larger hi-res version of the current thumbnail.
How can I detect when the user has completed scrolling? I do implement didEndDisplayingCell
, but that only tells me when a particular cell has scrolled off; it doesn't tell me when the scroll motion actually completes.
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionView : UIScrollView
UICollectionView
is a subclass of UIScrollView
. So if you have set the delegate and implemented UIScrollViewDelegate
, you should be able to detect this the same way as UIScrollView
.
For eg:-
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
As per documentation, the above method should tell when the scroll view has ended decelerating the scrolling movement.
Just to cover your bases you should implement both these UIScrollViewDelegate methods.
In some cases there may not be a deceleration (and scrollViewDidEndDecelerating
would not be called), for e.g., the page is fully scrolled in place. In those case do your update right there in scrollViewDidEndDragging
.
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
[self updateStuff];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self updateStuff];
}
An important fact to note here :
This method gets called on User initiated scrolls (i.e a Pan gesture)
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
On the other hand, this one gets called on all manually (programatically) initiated scrolls (like scrollRectToVisible
or scrollToItemAtIndexPath
)
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
Swift 3 version:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// Your code here
}
Swift 3 version of Abey M and D6mi 's answers:
When scroll is caused by user action
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if (!decelerate) {
//cause by user
print("SCROLL scrollViewDidEndDragging")
}
}
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
//caused by user
print("SCROLL scrollViewDidEndDecelerating")
}
When scroll is caused by code action (programmatically): (like "scrollRectToVisible" or "scrollToItemAtIndexPath")
public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
//caused by code
print("SCROLL scrollViewDidEndScrollingAnimation")
}
Notes:
- Put these functions in your UIScrollViewDelegate or UICollectionViewDelegate delegate.
- if you don't have a separate delegate, make your current class extend a UIScrollViewDelegate op top of your class file
.
open class MyClass: NSObject , UICollectionViewDelegate
and somewhere in your viewWillAppear make the class its own delegate
override open func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// ...
self.myScrollView.delegate = self
// ...
}
if you want to use the visible indexpath:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self scrollingFinish];
}
- (void)scrollingFinish {
if([self.collectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionHeader]){
NSIndexPath *firstVisibleIndexPath = [[self.collectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionHeader] firstObject];
[self.collectionView scrollToItemAtIndexPath:firstVisibleIndexPath atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
}