Автоматическая прокрутка UICollectionView к ячейке в IndexPath

Перед загрузкой представления коллекции пользователь устанавливает количество изображений в массиве просмотра коллекции. Все ячейки не помещаются на экране. У меня 30 ячеек и только 6 на экране.

Вопрос: как автоматически перейти к ячейке с желаемым изображением при загрузке UICollectionView?

Ответ 1

Новый отредактированный ответ:

Добавьте это в viewDidLayoutSubviews

СВИФТ

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let indexPath = IndexPath(item: 12, section: 0)
    self.collectionView.scrollToItem(at: indexPath, at: [.centeredVertically, .centeredHorizontally], animated: true)
}

Обычно, .centerVertically имеет место

ObjC

-(void)viewDidLayoutSubviews {
   [super viewDidLayoutSubviews];
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:12 inSection:0];
   [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically | UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}

Старый ответ работает на старых iOS

Добавьте это в viewWillAppear:

[self.view layoutIfNeeded];
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];

Ответ 2

Я обнаружил, что прокрутка в viewWillAppear может работать viewWillAppear поскольку представление коллекции еще не завершило макет; Вы можете перейти к неправильному элементу.

Я также обнаружил, что прокрутка в viewDidAppear вызовет кратковременное мигание не прокручиваемого представления.

И, если вы будете каждый раз viewDidLayoutSubviews, пользователь не сможет прокручивать вручную, потому что некоторые макеты коллекций вызывают макет подпредставления при каждой прокрутке.

Вот что я нашел надежно работает:

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    // If we haven't done the initial scroll, do it once.
    if (!self.initialScrollDone) {
        self.initialScrollDone = YES;

        [self.collectionView scrollToItemAtIndexPath:self.myInitialIndexPath
                                    atScrollPosition:UICollectionViewScrollPositionRight animated:NO];
    }
}

Ответ 3

Я полностью согласен с приведенным выше ответом. Единственное, что для меня было установлено решение в коде viewDidAppear

viewDidAppear 
{
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
}

Когда я использовал viewWillAppear, прокрутка не работала.

Ответ 4

это, казалось, сработало для меня, похоже на другой ответ, но имеет некоторые отличительные отличия:

- (void)viewDidLayoutSubviews
{     
   [self.collectionView layoutIfNeeded];
   NSArray *visibleItems = [self.collectionView indexPathsForVisibleItems];
   NSIndexPath *currentItem = [visibleItems objectAtIndex:0];
   NSIndexPath *nextItem = [NSIndexPath indexPathForItem:someInt inSection:currentItem.section];

   [self.collectionView scrollToItemAtIndexPath:nextItem atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
}

Ответ 5

Swift:

your_CollectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)

Swift 3

let indexPath = IndexPath(row: itemIndex, section: sectionIndex)

collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.right, animated: true)

Позиция прокрутки:

UICollectionViewScrollPosition.CenteredHorizontally / UICollectionViewScrollPosition.CenteredVertically

Ответ 6

Вы можете использовать GCD для отправки прокрутки в следующую итерацию основного цикла запуска в viewDidLoad для достижения такого поведения. Прокрутка будет выполняться до отображения вида коллекции на экране, поэтому мигание не будет.

- (void)viewDidLoad {
    dispatch_async (dispatch_get_main_queue (), ^{
        NSIndexPath *indexPath = YOUR_DESIRED_INDEXPATH;
        [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
    });
}

Ответ 7

Я бы рекомендовал сделать это в collectionView: willDisplay:. Тогда вы можете быть уверены, что делегат представления коллекции поставляет что-то. Вот мой пример:

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    /// this is done to set the index on start to 1 to have at index 0 the last image to have a infinity loop
    if !didScrollToSecondIndex {
        self.scrollToItem(at: IndexPath(row: 1, section: 0), at: .left, animated: false)
        didScrollToSecondIndex = true
    }
}

Ответ 8

Все ответы здесь - хаки. Я нашел лучший способ прокрутки просмотра коллекции где-то после relaodData:
Представление подкласса коллекции, какой бы макет вы не использовали, переопределить метод prepareLayout, после того, как супер-вызов установил то, что когда-либо компенсировало вам.
ex: fooobar.com/info/74612/...