UICollectionView anime les éléments après l'appel de reloadItemsAtIndexPaths (animation de fondu).
Existe-t-il un moyen d'éviter cette animation?
iOS 6
Réponses:
Il est à noter que si vous ciblez iOS 7 et supérieur, vous pouvez utiliser la nouvelle UIView
méthode performWithoutAnimation:
. Je soupçonne que sous le capot, cela fait à peu près la même chose que les autres réponses ici (désactivation temporaire des UIView
animations / actions Core Animation), mais la syntaxe est agréable et propre.
Donc pour cette question en particulier ...
Objectif c:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Rapide:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Bien entendu, ce principe peut s'appliquer à toute situation dans laquelle vous souhaitez vous assurer qu'un changement n'est pas animé.
Vous pouvez également essayer ceci:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
J'ai également constaté que si vous enveloppez performBatchUpdates
un bloc d'animation UIView, l'animation UIView est utilisée à la place de l'animation par défaut, vous pouvez donc simplement définir la durée de l'animation sur 0, comme ceci:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
C'est très cool si vous souhaitez utiliser des animations élastiques iOS 7 lors des insertions et des suppressions!
performBatchUpdates
intérieur animateWithDuration
est génial! Merci pour le conseil!
UICollectionView anime les éléments après l'appel de reloadItemsAtIndexPaths (animation de fondu).
Existe-t-il un moyen d'éviter cette animation?
iOS 6
Je suppose que vous utilisez un FlowLayout. Puisque vous essayez de vous débarrasser de l'animation de fondu, essayez ceci:
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
}
}
C'est une question très ancienne, donc vous ne ciblez probablement plus iOS 6. Je travaillais personnellement sur tvOS 11 et j'avais la même question, c'est donc ici pour tous ceux qui rencontrent le même problème.
J'ai écrit une catégorie sur UICollectionView pour faire exactement cela. L'astuce consiste à désactiver toutes les animations lors du rechargement:
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
CATransaction.setDisableActions(true)
un raccourci pour cela.
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
Voici une version Swift 3 performBatchUpdates
sans animation vers un fichier UICollectionView
. J'ai trouvé que cela fonctionnait mieux pour moi que collectionView.reloadData()
parce que cela réduisait l'échange de cellules lorsque des enregistrements étaient insérés.
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];
}
}
Juste pour ajouter mon 0,02 $, j'ai essayé les deux versions de la réponse sélectionnée, et la méthode originale fonctionnait mieux pour mes besoins. Je travaille sur une vue de calendrier à défilement infini qui permet à un utilisateur d'entrer dans le calendrier à une semaine donnée, puis de balayer d'avant en arrière et de sélectionner des jours individuels pour filtrer une liste.
Dans ma mise en œuvre, afin de garder les choses performantes sur les appareils plus anciens, le tableau des dates qui représentent la vue du calendrier doit être relativement petit, ce qui signifie contenir environ 5 semaines de dates, avec l'utilisateur au milieu à la 3e semaine. Le problème avec l'utilisation de la deuxième approche est qu'il y a une deuxième étape où vous devez faire défiler la vue de la collection vers le milieu sans animation, ce qui donne une apparence très irrégulière pour une raison quelconque avec l'animation de base bloquée.
Mon code:
[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)
}