UICollectionView animer des éléments après que reloadItemsAtIndexPaths est appelé (animation en fondu).
Y a-t-il un moyen d'éviter cette animation?
iOS 6
Vous pouvez aussi 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
dans un bloc d'animation UIView, l'animation UIView est utilisée à la place de l'animation par défaut. Vous pouvez donc définir la durée de l'animation sur 0, comme suit:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
C'est super cool si vous voulez utiliser les animations élastiques d'iOS 7 pendant les insertions et les suppressions!
Notez que si vous ciblez iOS 7 ou supérieur, vous pouvez utiliser la nouvelle méthode UIView
performWithoutAnimation:
. Je suppose que sous le capot, cela correspond à peu près aux autres réponses ici (désactivation temporaire de UIView
animations/actions Core Animation), mais la syntaxe est agréable et nette.
Donc, pour cette question en particulier ...
Objective-C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Swift:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Bien sûr, ce principe peut être appliqué à toute situation dans laquelle vous souhaitez vous assurer qu'un changement est pas animé .
UICollectionView animer des éléments après que reloadItemsAtIndexPaths est appelé (animation en fondu).
Y a-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, vous ne ciblez donc probablement plus iOS 6. Personnellement, je travaillais sur tvOS 11 et je posais la même question. C’est donc ici pour tous ceux qui ont le même problème.
J'ai écrit un catégorie sur UICollectionView pour le faire. 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];
}
Voici une version de Swift 3 à performBatchUpdates
sans animation à un 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 a mieux fonctionné pour mes besoins. Je travaille sur une vue de calendrier défilant à l'infini qui permet à un utilisateur d'entrer dans le calendrier une semaine donnée, puis de faire glisser votre doigt et de sélectionner des jours individuels pour le filtrage d'une liste.
Dans mon implémentation, afin de conserver les performances sur les appareils plus anciens, le tableau de dates représentant la vue du calendrier doit être relativement petit, ce qui signifie qu’il faut conserver environ 5 semaines de dates, l’utilisateur étant au centre à la 3e semaine. Le problème avec l'utilisation de la deuxième approche est qu'il existe une deuxième étape dans laquelle vous devez faire défiler la vue de collection au 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];
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}