web-dev-qa-db-ja.com

UICollectionView:スクロールが停止したことを検出する方法

UICollectionViewを使用して、サムネイルのセットをすばやくスクロールします。スクロールが終了したら、現在のサムネイルの大きな高解像度バージョンを表示したいと思います。

ユーザーがスクロールを完了したことを検出するにはどうすればよいですか?私はdidEndDisplayingCellを実装していますが、それは特定のセルがスクロールオフしたときだけを教えてくれます。スクロールモーションが実際にいつ完了するかはわかりません。

55
George Armhold
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionView : UIScrollView

UICollectionViewUIScrollViewのサブクラスです。したがって、デリゲートを設定してUIScrollViewDelegateを実装している場合、UIScrollViewと同じ方法でこれを検出できるはずです。

例えば:-

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

ドキュメント に従って、上記のメソッドは、スクロールビューがスクロール動作の減速を終了したことを通知する必要があります。

116
iDev

ベースをカバーするために、これら両方のUIScrollViewDelegateメソッドを実装する必要があります。場合によっては、減速が発生しない可能性があります(scrollViewDidEndDeceleratingは呼び出されません)。たとえば、ページが完全にスクロールされます。その場合は、scrollViewDidEndDraggingで更新を行ってください。

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

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
  [self updateStuff];
}
54
Abey M

ここで注意すべき重要な事実:

このメソッドは、ユーザーが開始したスクロール(つまり、パンジェスチャー)で呼び出されます

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

一方、これは手動で(プログラムで)開始されたすべてのスクロール(scrollRectToVisiblescrollToItemAtIndexPathなど)で呼び出されます

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
31
D6mi

Swift 3バージョン:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    // Your code here
}
9
Mr Stanev

Abey MとD6miの回答のSwift 3バージョン:

スクロールがユーザーのアクションによって引き起こされた場合

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」や「scrollToItemAtIndexPath」など)

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

ノート:

  • これらの関数をUIScrollViewDelegateまたはUICollectionViewDelegateデリゲートに配置します。
  • 個別のデリゲートがない場合、現在のクラスでUIScrollViewDelegateをクラスファイルのop topに拡張します

open class MyClass: NSObject , UICollectionViewDelegate

そしてあなたのviewWillAppearのどこかでクラスを独自のデリゲートにします

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

表示可能なインデックスパスを使用する場合:

- (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];
    }
}
0
Ofir Malachi