2013-02-14 336 views
41

我正在使用UICollectionView快速滾動縮略圖集。一旦滾動結束,我想顯示當前縮略圖的更大的高分辨率版本。UICollectionView:如何檢測滾動停止

如何檢測用戶何時完成滾動?我確實實現了didEndDisplayingCell,但這隻會告訴我某個特定單元格是否已經滾動;它並沒有告訴我滾動動作何時完成。

回答

97
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionView : UIScrollView 

UICollectionViewUIScrollView的子類。因此,如果您已設置代理並實施了UIScrollViewDelegate,則應該能夠以與UIScrollView相同的方式檢測到此情況。

對於例如: -

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; 

作爲每documentation,上述方法中,當滾動視圖已經結束減速滾動移動應該告訴。

+6

輝煌。你不知道這多少令人討厭的代碼救了我。我試圖在我的UICollectionViewFlowLayout中使用shouldInvalidateLayoutForBoundsChange回調來監視它。什麼是n00b。 – 2013-05-11 21:54:59

+0

請參閱下面關於scrollViewDidEndScrollingAnimation的D6mi的註釋。不會調用scrollViewDidEndDecelerating進行編程滾動。 – RajV 2016-10-24 11:42:02

+1

事實上,我不明白爲什麼當前的答案是接受的,它不工作'scrollViewDidEndDecelerating'不叫'但是像D6mi說的那樣,'scrollViewDidEndScrollingAnimation'叫 – AkademiksQc 2016-12-16 15:03:52

44

只是爲了覆蓋你的基地,你應該實現這兩個UIScrollViewDelegate方法。 在某些情況下,可能沒有減速(並且不會調用scrollViewDidEndDecelerating),例如,頁面已完全滾動到位。在這種情況下,請在scrollViewDidEndDragging的地方進行更新。

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 
{ 
    if (!decelerate) { 
    [self updateStuff]; 
    } 
} 

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    [self updateStuff]; 
} 
+6

謝謝您分享!這應該是被接受的答案b/c OP問「滾動已停止」 - 如果沒有兩種方法,用戶可以輕鬆向下滾動收集視圖並釋放手指而不彈出,並且不會調用「scrollViewDidEndDecelerating」,「scrollViewDidEndDragging」會。感謝您發佈這個答案。 – 2014-07-18 21:34:10

21

一個重要的事實這裏要注意:

調用此方法對用戶發起的卷軸(即泛手勢)

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; 

在另一方面,這個人會呼籲所有手動(編程)啓動的卷軸(如「scrollRectToVisible」或「scrollToItemAtIndexPath」)

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView 
4

斯威夫特3版本:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 
    // Your code here 
} 
+0

謝謝!它運作良好。 – Raja 2017-11-07 14:49:35

0
如果你想使用可視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]; 
    } 
} 
1

斯威夫特3版本Abey M和D6mi的答案:

當滾動由用戶造成的動作

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") 
} 

當滾動是由代碼動作(以編程方式)引起:(如「scrollRectToVisible」或「scrollT oItemAtIndexPath「)

public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { 
    //caused by code 
    print("SCROLL scrollViewDidEndScrollingAnimation") 
} 

注:

  • 把這些功能在您的UIScrollViewDelegate或UICollectionViewDelegate委託。
  • ,如果你沒有一個單獨的委託,讓你的當前類擴展您的類文件

的UIScrollViewDelegate OP頂部。

open class MyClass: NSObject , UICollectionViewDelegate 

和地方在你的viewWillAppear中讓類自己的委託

override open func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated) 
    // ... 
    self.myScrollView.delegate = self 
    // ... 
}