UICollectionview scrollToItemAtIndexPath, не загружая видимые ячейки до завершения анимации

У меня есть UICollectionView со 142 ячейками. 7.5 видны одновременно.

Я перемещаю ячейку с indexPath 0 на 100. Но я также хочу прокрутить до этой новой позиции.

Код ниже работает нормально. Но он анимирует перемещение и прокрутку, но затем загружает ячейки перед центральной/перемещенной ячейкой и за ней. Я думаю, это потому, что клетки можно использовать повторно. но со 142 я не могу предварительно загрузить их все

Это не самый приятный эффект, я хотел бы предварительно загрузить ячейки, окружающие новую позицию, 4 до и 4 после indexPath 100, а затем увидеть анимацию перемещения и прокрутки. Вы можете помочь, пожалуйста?

UIView.animateWithDuration(animationSpeed, animations: {() -> Void in
    self.collectionView.layoutIfNeeded()
    self.collectionView.scrollToItemAtIndexPath(NSIndexPath(forItem:self.indexPathSelected.row, 
                                                 inSection:0), 
                                                 atScrollPosition: .CenteredHorizontally, 
                                                 animated: true)

})

person ThundercatChris    schedule 11.01.2016    source источник


Ответы (5)


Swift 3.0 или выше

добавьте «view.layoutIfNeeded ()» перед реализацией метода scrollToItem, в идеале в viewWillAppear

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
view.layoutIfNeeded()
  colView.scrollToItem(at: IndexPath(item: 4, section: 0), at: .centeredHorizontally, animated: true)}
person Hiren Panchal    schedule 21.02.2017

Я использую dispatch_async для обновления пользовательского интерфейса, и это работает.

let numberOfSections = self.collectionView.numberOfSections()
let numberOfRows = self.collectionView.numberOfItemsInSection(numberOfSections-1)

    if numberOfRows > 0 {
        dispatch_async(dispatch_get_main_queue(), {
            let indexPath = NSIndexPath(forRow: numberOfRows-1, inSection: (numberOfSections-1))
            self.collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
        })
    }
person Willjay    schedule 25.04.2016
comment
Это также работает, когда вы пытаетесь прокрутить представлениеWillAppear(_:). Например, я только что сделал это, чтобы начать с элемента № 2 из 5 индексов, поэтому мое представление коллекции начинается в середине, а не в начале, когда появляется контроллер представления. - person Xavier L.; 30.03.2018

Единственный ответ, который я нашел, это добавить несколько секунд к анимации. Таким образом, ячейки загружаются, когда приходит прокрутка

person ThundercatChris    schedule 13.01.2016
comment
Покажите примеры того, как это сделать - person Edu; 03.09.2017

Лучшим решением, которое я нашел, было использование DispatchQueue.

Свифт 4.2:

 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if let index = items.firstIndex(of: preSelectedItem) {
        DispatchQueue.main.async {
            self.collectionView.scrollToItem(at: IndexPath(item: index, section: 0), at: .top, animated: false)
        }
    }
}
person Politta    schedule 06.11.2018

@ Ответ Политы правильный. Вот как вы можете реализовать то, что хотите, в Objective C:

- (void)scrollToBottomWithoutAnimation{
    NSInteger lastVisibleRowIndex = (NSInteger)self.myItems.count - 1;
    NSIndexPath *lastVisibleIndexPath = [NSIndexPath indexPathForRow: lastVisibleRowIndex inSection:0];
    [self.collectionView scrollToItemAtIndexPath:lastVisibleIndexPath atScrollPosition: UICollectionViewScrollPositionCenteredVertically animated:NO];
}

В вашем методе viewWillAppear:

dispatch_async(dispatch_get_main_queue(), ^{
    [self scrollToBottomWithoutAnimation];
});
person Eray Alparslan    schedule 31.08.2020