Подтвердить что ты не робот

UICollectionView текущий видимый индекс ячейки

Я использую UICollectionView первый раз в своем приложении для iPad. Я установил UICollectionView таким образом, чтобы размер и размер ячейки были одинаковыми, это означает, что сразу отображается ячейка.

Проблема: Теперь, когда пользователь прокручивает UICollectionView, мне нужно знать, какая ячейка видна, мне нужно обновить другие элементы пользовательского интерфейса при изменении. Для этого я не нашел ни одного метода делегата. Как я могу достичь этого?

Код:

[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???

4b9b3361

Ответ 1

Метод [collectionView visibleCells] предоставляет вам все видимые массивы visibleCells. Используйте его, когда хотите получить

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

Ответ 2

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

Это особенно хорошо работает, когда каждый элемент в представлении коллекции занимает весь экран.

Ответ 3

Рабочие ответы, объединенные в 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)!

        print(visibleIndexPath)

    }

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)

    let visibleIndexPath: IndexPath = collectionView.indexPathForItem(at: visiblePoint)!

    print(visibleIndexPath)
}

Ответ 4

Для полноты, это метод, который в конечном итоге работает для меня. Это была комбинация методов @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);
}

Ответ 5

Просто хочу добавить для других: по какой-то причине я не получил ячейку, которая была видна пользователю, когда я прокручивал предыдущую ячейку в коллекцииView с помощью pagingEnabled.

Итак, я вставляю код внутри dispatch_async, чтобы дать ему некоторый "воздух", и это работает для меня.

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


            [visibleCell doSomthing];
        });
}

Ответ 6

Скорее всего, лучше использовать методы 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)
}

Ответ 7

Для 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)
}

Ответ 8

Вы можете использовать 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);
        }

    }

Ответ 9

Swift 3.0

Простейшее решение, которое даст вам indexPath для видимых ячеек.

yourCollectionView.indexPathsForVisibleItems 

вернет массив указательного пути.

Просто возьмите первый объект из массива, как это.

yourCollectionView.indexPathsForVisibleItems.first

Я предполагаю, что он тоже отлично работает с Objective-C.

Ответ 10

UICollectionView текущий видимый индекс ячейки: Swift 3

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

     return nil
}

Ответ 11

Это старый вопрос, но в моем случае...

- (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;
}

Ответ 12

преобразование @Ответ Энтони на Swift 3.0 отлично работал у меня:

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 index is : \(visibleIndexPath?.row)!")
}

Ответ 13

попробуйте это, он работает. (в приведенном ниже примере я имею, например, 3 ячейки.)

    func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    let visibleRect = CGRect(origin: self.collectionView.contentOffset, size: self.collectionView.bounds.size)
    let visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect))
    let visibleIndexPath = self.collectionView.indexPathForItemAtPoint(visiblePoint)
    if let v = visibleIndexPath {
        switch v.item {
        case 0: setImageDescription()
            break
        case 1: setImageConditions()
            break
        case 2: setImageResults()
            break
        default: break
        }
    }