web-dev-qa-db-ja.com

UICollectionViewの現在の表示セルインデックス

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

問題:ユーザーが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];

私が試したもの:

UICollectionViewUIScrollViewに準拠しているため、ユーザースクロールがUIScrollViewDelegateメソッドで終了する

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

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

97
Irfan DANISH

メソッド[collectionView visibleCells]は、必要なすべてのvisibleCells配列を提供します。あなたが取得したいときにそれを使用してください

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    for (UICollectionViewCell *cell in [self.mainImageCollection visibleCells]) {
        NSIndexPath *indexPath = [self.mainImageCollection indexPathForCell:cell];
        NSLog(@"%@",indexPath);
    }
}
118
LE SANG

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];

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

Swiftバージョン

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)
150
Anthony

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)

    }

Swift 3&Swift 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)
}
68
Sam Bing

完全を期すために、これは私のために働いてしまった方法です。 @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);
}
18
Vincil Bishop

UICollectionViewDelegateメソッドを使用するのがおそらく最善でしょう:(Swift 3)

// Called before the cell is displayed    
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    print(indexPath.row)
}

// Called when the cell is displayed
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    print(indexPath.row)
}
9
Mr Stanev

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

そこで、dispatch_async内にコードを挿入して、「空気」を与えます。

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


            [visibleCell doSomthing];
        });
}
8
user1105951

Swift 3.0の場合

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let visibleRect = CGRect(Origin: colView.contentOffset, size: colView.bounds.size)
    let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
    let indexPath = colView.indexPathForItem(at: visiblePoint)
}
7
Hiren Panchal

Swift 3.0

可視セルのindexPathを提供する最も簡単なソリューション。

yourCollectionView.indexPathsForVisibleItems 

indexpathの配列を返します。

このように配列から最初のオブジェクトを取得するだけです。

yourCollectionView.indexPathsForVisibleItems.first

Objective-Cでも問題なく動作するはずです。

6
Anil Kukadeja

UICollectionViewの現在の表示セルインデックス:Swift 3

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

     return nil
}
4
Mihail Salari

このためにscrollViewDidEndDecelerating:を使用できます

//@property (strong, nonatomic) IBOutlet UICollectionView *collectionView;

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

        for (UICollectionViewCell *cell in [self.collectionView visibleCells]) {
            NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
            NSUInteger lastIndex = [indexPath indexAtPosition:[indexPath length] - 1];
            NSLog(@"visible cell value %d",lastIndex);
        }

    }
2
raaz

@Anthonyの答えをSwift 3.に変換すると、私にとって完璧に機能しました。

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    var visibleRect = CGRect()
    visibleRect.Origin = yourCollectionView.contentOffset
    visibleRect.size = yourCollectionView.bounds.size
    let visiblePoint = CGPoint(x: CGFloat(visibleRect.midX), y: CGFloat(visibleRect.midY))
    let visibleIndexPath: IndexPath? = yourCollectionView.indexPathForItem(at: visiblePoint)
    print("Visible cell's index is : \(visibleIndexPath?.row)!")
}
1
Nilesh Pol

このスニペットも確認​​してください

let isCellVisible = collectionView.visibleCells.map { collectionView.indexPath(for: $0) }.contains(inspectingIndexPath)
0
Nik Kov

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

- (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;
}
0
Hwangho Kim