136

UICollectionViewiPadアプリケーションで初めて使用しています。UICollectionViewサイズとセルサイズが同じになるように設定しました。つまり、一度にセルが1回だけ表示されることを意味します。

問題: ユーザーがスクロールUICollectionViewすると、どのセルが表示されているかを知る必要があり、変更時に他の UI 要素を更新する必要があります。このためのデリゲートメソッドが見つかりませんでした。どうすればこれを達成できますか?

コード:

[self.mainImageCollection setTag:MAIN_IMAGE_COLLECTION_VIEW];
[self.mainImageCollection registerClass:[InspirationMainImageCollectionCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
[self.mainImageFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.mainImageFlowLayout setMinimumInteritemSpacing:0.0f];
[self.mainImageFlowLayout setMinimumLineSpacing:0.0f];
self.mainImageFlowLayout.minimumLineSpacing = 0;
[self.mainImageCollection setPagingEnabled:YES];
[self.mainImageCollection setShowsHorizontalScrollIndicator:NO];
[self.mainImageCollection setCollectionViewLayout:self.mainImageFlowLayout];

私が試したこと:

UICollectionView準拠して、メソッドUIScrollViewでユーザースクロールが終了したときに取得しましたUIScrollViewDelegate

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

しかし、上記の関数内で、現在表示されているセルのインデックスを取得するにはどうすればよいUICollectionViewですか?

4

16 に答える 16

209

indexPathsForVisibleItemsほとんどの状況で機能する可能性がありますが、複数のインデックス パスを含む配列が返される場合があり、目的のパスを見つけるのが難しい場合があります。そのような状況では、次のようなことができます。

CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];

これは、コレクション ビューの各アイテムが画面全体を占める場合に特に効果的です。

迅速なバージョン

let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
let visibleIndexPath = collectionView.indexPathForItem(at: visiblePoint)
于 2014-06-24T21:28:34.473 に答える
92

スイフト5

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    var visibleRect = CGRect()

    visibleRect.origin = collectionView.contentOffset
    visibleRect.size = collectionView.bounds.size

    let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)

    guard let indexPath = collectionView.indexPathForItem(at: visiblePoint) else { return } 

    print(indexPath)
}

Swift 2.2 で結合された実用的な回答:

 func scrollViewDidEndDecelerating(scrollView: UIScrollView) {

        var visibleRect = CGRect()

        visibleRect.origin = self.collectionView.contentOffset
        visibleRect.size = self.collectionView.bounds.size

        let visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect))

        let visibleIndexPath: NSIndexPath = self.collectionView.indexPathForItemAtPoint(visiblePoint)

        guard let indexPath = visibleIndexPath else { return } 
        print(indexPath)

    }
于 2016-04-11T12:44:49.507 に答える
19

完全を期すために、これは私のために働いた方法です。@Anthony と @iAn のメソッドの組み合わせでした。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
      CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
      CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
      NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
      NSLog(@"%@",visibleIndexPath);
}
于 2014-09-18T13:06:44.087 に答える
14

UICollectionView の現在の可視セル インデックス: Swift 3、4、および 5+

var visibleCurrentCellIndexPath: IndexPath? {
    for cell in self.collectionView.visibleCells {
        let indexPath = self.collectionView.indexPath(for: cell)
        return indexPath
     }
        
     return nil
}

拡張子として:

extension UICollectionView {
  var visibleCurrentCellIndexPath: IndexPath? {
    for cell in self.visibleCells {
      let indexPath = self.indexPath(for: cell)
      return indexPath
    }
    
    return nil
  }
}

使用法:

if let indexPath = collectionView.visibleCurrentCellIndexPath { 
   /// do something
}
于 2016-11-24T12:26:05.360 に答える
10

他の人のために追加したいだけです: 何らかの理由で、pagingEnabled で collectionView の前のセルにスクロールしているときに、ユーザーに表示されたセルを取得できませんでした。

したがって、dispatch_async 内にコードを挿入して「空気」を与えると、これが機能します。

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    dispatch_async(dispatch_get_main_queue(), ^{
            UICollectionViewCell * visibleCell= [[self.collectionView visibleCells] objectAtIndex:0];


            [visibleCell doSomthing];
        });
}
于 2015-03-21T21:54:44.187 に答える
0

これは古い質問ですが、私の場合...

- (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView {

    _m_offsetIdx = [m_cv indexPathForCell:m_cv.visibleCells.firstObject].row;
}

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    _m_offsetIdx = [m_cv indexPathForCell:m_cv.visibleCells.lastObject].row;
}
于 2016-05-23T14:00:13.443 に答える
-1

スウィフト 3 & スウィフト 4:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
   var visibleRect = CGRect()

   visibleRect.origin = collectionView.contentOffset
   visibleRect.size = collectionView.bounds.size

   let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)

   guard let indexPath = collectionView.indexPathForItem(at: visiblePoint) else { return } 

   print(indexPath[1])
}

+1を追加するよりも実際の数を表示したい場合

于 2018-11-11T07:01:36.150 に答える