UICollectionView animuje elementy po wywołaniu reloadItemsAtIndexPaths (animacja zanikania).
Czy jest sposób, aby uniknąć tej animacji?
iOS 6
Warto zauważyć, że jeśli celujesz w system iOS 7 i nowszy, możesz użyć nowej UIView
metody performWithoutAnimation:
. Podejrzewam, że pod maską działa to podobnie jak inne odpowiedzi tutaj (tymczasowo wyłączamUIView
animacji / akcji Core Animation), ale składnia jest ładna i przejrzysta.
A więc w szczególności w przypadku tego pytania ...
Cel C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Szybki:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Oczywiście tę zasadę można zastosować w każdej sytuacji, w której chcesz mieć pewność, że zmiana nie jest animowana.
Możesz także spróbować tego:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO]; [collectionView performBatchUpdates:^{ [collectionView reloadItemsAtIndexPaths:indexPaths]; } completion:^(BOOL finished) { [UIView setAnimationsEnabled:YES]; }];
Edytować:
Odkryłem również, że jeśli
performBatchUpdates
zawiniesz blok animacji UIView, zamiast domyślnej animacji zostanie użyta animacja UIView, więc możesz po prostu ustawić czas trwania animacji na 0, na przykład:[UIView animateWithDuration:0 animations:^{ [collectionView performBatchUpdates:^{ [collectionView reloadItemsAtIndexPaths:indexPaths]; } completion:nil]; }];
Jest to super fajne, jeśli chcesz używać sprężystych animacji iOS 7 podczas wstawiania i usuwania!
źródło
performBatchUpdates
środkuanimateWithDuration
jest genialne! Dzięki za wskazówkę!Zakładam, że używasz FlowLayout. Ponieważ próbujesz pozbyć się animacji zanikania, spróbuj tego:
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 } }
To bardzo stare pytanie, więc prawdopodobnie nie masz już na celu iOS 6. Osobiście pracowałem nad tvOS 11 i miałem to samo pytanie, więc to jest tutaj dla każdego, kto ma ten sam problem.
źródło
Napisałem kategorię na UICollectionView, aby to zrobić. Sztuczka polega na tym, aby wyłączyć wszystkie animacje podczas przeładowywania:
if (!animated) { [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; } [self reloadItemsAtIndexPaths:indexPaths]; if (!animated) { [CATransaction commit]; }
źródło
CATransaction.setDisableActions(true)
jako skrót.extension UICollectionView { func reloadWithoutAnimation(){ CATransaction.begin() CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions) self.reloadData() CATransaction.commit() } }
źródło
Oto wersja Swift 3
performBatchUpdates
bez animacji do plikuUICollectionView
. Okazało się, że działa to lepiej dla mnie niżcollectionView.reloadData()
dlatego, że ogranicza wymianę komórek po wstawieniu rekordów.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 }) } }
źródło
- (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]; } }
źródło
Aby dodać 0,02 $, wypróbowałem obie wersje wybranej odpowiedzi i oryginalny sposób działał lepiej dla moich celów. Pracuję nad nieskończonym przewijanym widokiem kalendarza, który pozwala użytkownikowi wejść do kalendarza w danym tygodniu, a następnie przesuwać palcem w przód iw tył i wybierać poszczególne dni do filtrowania listy.
W mojej implementacji, aby zachować wydajność na starszych urządzeniach, tablica dat reprezentująca widok kalendarza musi być stosunkowo mała, co oznacza przechowywanie dat o wartości około 5 tygodni, z użytkownikiem w środku w trzecim tygodniu. Problem ze stosowaniem drugiego podejścia polega na tym, że jest drugi krok, w którym musisz przewinąć widok kolekcji z powrotem do środka bez animacji, co z jakiegoś powodu powoduje bardzo postrzępiony wygląd z zablokowaną animacją podstawową.
Mój kod:
[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];
źródło
func reloadRowsWithoutAnimation(at indexPaths: [IndexPath]) { let contentOffset = collectionView.contentOffset UIView.setAnimationsEnabled(false) collectionView.performBatchUpdates { collectionView.reloadItems(at: indexPaths) } UIView.setAnimationsEnabled(true) collectionView.setContentOffset(contentOffset, animated: false) }
źródło