UICollectionView anima gli elementi dopo che è stato chiamato reloadItemsAtIndexPaths (fade animation).
C'è un modo per evitare questa animazione?
iOS 6
Risposte:
Vale la pena notare che se stai prendendo di mira iOS 7 e versioni successive, puoi utilizzare il nuovo UIView
metodo performWithoutAnimation:
. Sospetto che sotto il cofano questo stia facendo più o meno lo stesso delle altre risposte qui (disabilitando temporaneamente le UIView
animazioni / le azioni di animazione principale), ma la sintassi è bella e pulita.
Quindi per questa domanda in particolare ...
Obiettivo-C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Swift:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Naturalmente questo principio può essere applicato a qualsiasi situazione in cui si desidera garantire che un cambiamento non sia animato.
Potresti anche provare questo:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
Ho anche scoperto che se performBatchUpdates
esegui il wrapping in un blocco di animazione UIView, l'animazione UIView viene utilizzata al posto dell'animazione predefinita, quindi puoi semplicemente impostare la durata dell'animazione su 0, in questo modo:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
Questo è molto interessante se desideri utilizzare le animazioni elastiche di iOS 7 durante gli inserimenti e le eliminazioni!
performBatchUpdates
all'interno animateWithDuration
è geniale! Grazie per il consiglio!
UICollectionView anima gli elementi dopo che è stato chiamato reloadItemsAtIndexPaths (fade animation).
C'è un modo per evitare questa animazione?
iOS 6
Presumo tu stia usando un FlowLayout. Dato che stai cercando di sbarazzarti dell'animazione in dissolvenza, prova questo:
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
}
}
Questa è una domanda molto vecchia, quindi probabilmente non stai più prendendo di mira iOS 6. Stavo lavorando personalmente su tvOS 11 e avevo la stessa domanda, quindi questo è qui per chiunque abbia lo stesso problema.
Ho scritto una categoria su UICollectionView per fare proprio questo. Il trucco è disabilitare tutte le animazioni durante il caricamento:
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
CATransaction.setDisableActions(true)
una scorciatoia per questo.
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
Ecco una versione di Swift 3 performBatchUpdates
senza animazione in un file UICollectionView
. Ho trovato che questo funzioni meglio per me piuttosto che collectionView.reloadData()
perché riduceva lo scambio di celle quando venivano inseriti i record.
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];
}
}
Solo per aggiungere i miei $ 0,02, ho provato entrambe le versioni della risposta selezionata e il modo originale ha funzionato meglio per i miei scopi. Sto lavorando su una visualizzazione del calendario a scorrimento infinito che consente a un utente di accedere al calendario in una determinata settimana, quindi scorrere avanti e indietro e selezionare i singoli giorni per filtrare un elenco.
Nella mia implementazione, per mantenere le cose performanti sui dispositivi più vecchi, la serie di date che rappresentano la visualizzazione del calendario deve essere mantenuta relativamente piccola, il che significa contenere circa 5 settimane di date, con l'utente al centro alla terza settimana. Il problema con l'utilizzo del secondo approccio è che c'è un secondo passaggio in cui è necessario scorrere la vista della raccolta fino al centro senza un'animazione, il che rende per qualche motivo un aspetto molto frastagliato con l'animazione di base bloccata.
Il mio codice:
[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];
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)
}