Избегайте анимации UICollectionView после reloadItemsAtIndexPaths
UICollectionView анимировать элементы после reloadItemsAtIndexPaths называется (fade animation).
есть ли способ избежать этой анимации?
iOS 6
8 ответов:
вы также можете попробовать это:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO]; [collectionView performBatchUpdates:^{ [collectionView reloadItemsAtIndexPaths:indexPaths]; } completion:^(BOOL finished) { [UIView setAnimationsEnabled:YES]; }];
Edit:
Я также обнаружил, что если вы оборачиваете
performBatchUpdates
в блоке анимации UIView анимация UIView используется вместо анимации по умолчанию, поэтому вы можете просто установить длительность анимации в 0, например:[UIView animateWithDuration:0 animations:^{ [collectionView performBatchUpdates:^{ [collectionView reloadItemsAtIndexPaths:indexPaths]; } completion:nil]; }];
это очень круто, если вы хотите использовать iOS 7 пружинистые анимации во время вставки и удаления!
стоит отметить, что если вы нацелены на iOS 7 и выше, вы можете использовать новый
UIView
методperformWithoutAnimation:
. Я подозреваю, что под капотом это делает почти то же самое, что и другие ответы здесь (временное отключениеUIView
анимация / основные действия анимации), но синтаксис хороший и чистый.Итак, для этого вопроса в особый...
Цель-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]; }
вот версия 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 }) } }
- (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 недель стоит даты, с пользователем в середине на 3-й неделе. Проблема с использованием второго подхода заключается в том, что есть второй шаг, на котором вам нужно прокрутить представление коллекции обратно в середину без анимации, что по какой-то причине создает очень неровный внешний вид с заблокированной базовой анимацией.
Мой Код:
[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];
UICollectionView анимировать элементы после reloadItemsAtIndexPaths называется (затухание анимации).
есть ли способ избежать этой анимации?
iOS 6
Я предполагаю, что вы используете FlowLayout. Так как вы пытаетесь избавиться от исчезающей анимации, попробуйте следующее:
import UIKit class NoFadeFlowLayout: UICollectionViewFlowLayout { override func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? { let attrs = super.initialLayoutAttributesForAppearingItem(at: itemIndexPath) attrs?.alpha = 1.0 return attrs } override func finalLayoutAttributesForDisappearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? { let attrs = super.finalLayoutAttributesForDisappearingItem(at: itemIndexPath) attrs?.alpha = 1.0 return attrs } }
Это очень старый вопрос, поэтому вы, вероятно, больше не ориентируетесь на iOS 6. Я лично работал над tvOS 11 и имел тот же вопрос, поэтому это вот для тех, кто приходит с той же проблемой.