UICollectionView anima los elementos después de que se llama a reloadItemsAtIndexPaths (animación atenuada).
¿Hay alguna forma de evitar esta animación?
ios 6
Vale la pena señalar que si tiene como objetivo iOS 7 y superior, puede usar el nuevo UIView
método performWithoutAnimation:
. Sospecho que debajo del capó esto está haciendo lo mismo que las otras respuestas aquí (deshabilitando temporalmente UIView
animaciones / acciones de animación principal), pero la sintaxis es agradable y limpia.
Entonces, para esta pregunta en particular ...
C objetivo:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Rápido:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Por supuesto, este principio se puede aplicar a cualquier situación en la que desee asegurarse de que un cambio no esté animado.
También puedes probar esto:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO]; [collectionView performBatchUpdates:^{ [collectionView reloadItemsAtIndexPaths:indexPaths]; } completion:^(BOOL finished) { [UIView setAnimationsEnabled:YES]; }];
Editar:
También descubrí que si envuelve
performBatchUpdates
un bloque de animación UIView, se usa la animación UIView en lugar de la animación predeterminada, por lo que puede establecer la duración de la animación en 0, así:[UIView animateWithDuration:0 animations:^{ [collectionView performBatchUpdates:^{ [collectionView reloadItemsAtIndexPaths:indexPaths]; } completion:nil]; }];
¡Esto es muy bueno si quieres usar animaciones elásticas de iOS 7 durante las inserciones y eliminaciones!
fuente
performBatchUpdates
interioranimateWithDuration
es genial! ¡Gracias por el consejo!Supongo que estás usando un FlowLayout. Ya que está tratando de deshacerse de la animación de desvanecimiento, intente esto:
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 } }
Esta es una pregunta muy antigua, por lo que probablemente ya no esté apuntando a iOS 6. Personalmente estaba trabajando en tvOS 11 y tenía la misma pregunta, así que esto está aquí para cualquiera que tenga el mismo problema.
fuente
Escribí una categoría en UICollectionView para hacer precisamente eso. El truco consiste en desactivar todas las animaciones mientras se recarga:
if (!animated) { [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; } [self reloadItemsAtIndexPaths:indexPaths]; if (!animated) { [CATransaction commit]; }
fuente
CATransaction.setDisableActions(true)
como una abreviatura para esto.extension UICollectionView { func reloadWithoutAnimation(){ CATransaction.begin() CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions) self.reloadData() CATransaction.commit() } }
fuente
Aquí hay una versión de Swift 3
performBatchUpdates
sin animación aUICollectionView
. Descubrí que esto funcionaba mejor para mí quecollectionView.reloadData()
porque reducía el intercambio de celdas cuando se insertaban registros.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 }) } }
fuente
- (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]; } }
fuente
Solo para agregar mis $ 0.02, probé ambas versiones de la respuesta seleccionada y la forma original funcionó mejor para mis propósitos. Estoy trabajando en una vista de calendario de desplazamiento infinito que permite que un usuario ingrese al calendario en una semana determinada y luego deslice hacia adelante y hacia atrás y seleccione días individuales para filtrar una lista.
En mi implementación, para que las cosas sigan funcionando en los dispositivos más antiguos, el conjunto de fechas que representan la vista del calendario debe mantenerse relativamente pequeño, lo que significa mantener fechas de aproximadamente 5 semanas, con el usuario en el medio en la tercera semana. El problema con el uso del segundo enfoque es que hay un segundo paso en el que tienes que desplazar la vista de la colección hacia el medio sin una animación, lo que hace que la apariencia sea muy irregular por alguna razón con la animación base bloqueada.
Mi código:
[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];
fuente
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) }
fuente