UICollectionView анимирует элементы после вызова reloadItemsAtIndexPaths (анимация fade).
Есть ли способ избежать этой анимации?
iOS 6
UICollectionView анимирует элементы после вызова reloadItemsAtIndexPaths (анимация fade).
Есть ли способ избежать этой анимации?
iOS 6
Вы также можете попробовать следующее:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
Я также обнаружил, что если вы обертываете performBatchUpdates
в блоке анимации UIView, анимация UIView используется вместо анимации по умолчанию, поэтому вы можете просто установить продолжительность анимации на 0, например:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
Это очень здорово, если вы хотите использовать анимацию iOS 7 при вставке и удалении!
Стоит отметить, что если вы ориентируетесь на iOS 7 и выше, вы можете использовать новый метод UIView
performWithoutAnimation:
. Я подозреваю, что под капотом это делает то же самое, что и другие ответы здесь (временно отключая анимацию UIView
/Core Animation), но синтаксис приятный и чистый.
Итак, для этого вопроса в частности...
Objective-C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Swift:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Конечно, этот принцип может быть применен для любой ситуации, в которой вы хотите, чтобы изменение было не анимированным.
Я написал категорию в UICollectionView, чтобы сделать именно это. Фокус в том, чтобы отключить все анимации во время перезагрузки:
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
- (void)reloadCollectionViewAnimated:(BOOL)animated {
if (animated) {
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:^(BOOL finished) {
}];
} else {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
[CATransaction commit];
}
}
Просто чтобы добавить мои $0,02, я попробовал обе версии выбранного ответа, и оригинальный способ работал лучше для моих целей. Я работаю над бесконечным просмотром календаря прокрутки, который позволяет пользователю вводить календарь на заданную неделю, а затем прокручивать назад и вперед и выбирать отдельные дни для фильтрации списка.
В моей реализации, чтобы сохранить производительность на более старых устройствах, массив дат, представляющих представление календаря, должен быть относительно небольшим, что означает, что он должен содержать даты в 5 недель, а пользователь в середине на третьем неделю. Проблема с использованием второго подхода заключается в том, что есть второй шаг, на котором вам нужно прокрутить представление коллекции до середины без анимации, что по какой-то причине создает очень неровную внешность с заблокированной базовой анимацией.
Мой код:
[UIView setAnimationsEnabled:NO];
[self.collectionView performBatchUpdates:^{
[self.collectionView deleteItemsAtIndexPaths:indexPathDeleteArray];
[self.collectionView insertItemsAtIndexPaths:indexPathAddArray];
} completion:NULL];
[UIView setAnimationsEnabled:YES];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:14 inSection:0];
[self.collectionView scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
Вот версия Swift 3 до performBatchUpdates
без анимации до UICollectionView
. Я нашел, что это работает лучше для меня, чем collectionView.reloadData()
, потому что это уменьшило обмен ячейки при вставке записей.
func appendCollectionView(numberOfItems count: Int){
// calculate indexes for the items to be added
let firstIndex = dataItems.count - count
let lastIndex = dataItems.count - 1
var indexPaths = [IndexPath]()
for index in firstIndex...lastIndex {
let indexPath = IndexPath(item: index, section: 0)
indexPaths.append(indexPath)
}
UIView.performWithoutAnimation {
self.collectionView.performBatchUpdates({ () -> Void in
self.collectionView.insertItems(at: indexPaths)
}, completion: { (finished) -> Void in
})
}
}
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}