UICollectionView animiert Elemente, nachdem reloadItemsAtIndexPaths aufgerufen wurde (Animation verblassen).
Gibt es eine Möglichkeit, diese Animation zu vermeiden?
iOS 6
Antworten:
Sie können dies auch versuchen:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
Ich habe auch festgestellt, dass performBatchUpdates
beim Umschließen eines UIView-Animationsblocks die UIView-Animation anstelle der Standardanimation verwendet wird, sodass Sie die Animationsdauer wie folgt auf 0 setzen können:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
Dies ist besonders cool, wenn Sie beim Einfügen und Löschen federnde iOS 7-Animationen verwenden möchten!
performBatchUpdates
Innen einwickeln animateWithDuration
ist genial! Danke für den Tipp!
Es ist erwähnenswert, dass Sie die neue UIView
Methode verwenden können, wenn Sie auf iOS 7 und höher abzielen performWithoutAnimation:
. Ich vermute, dass dies unter der Haube ähnlich funktioniert wie die anderen Antworten hier (vorübergehende Deaktivierung von UIView
Animationen / Core-Animationsaktionen), aber die Syntax ist nett und sauber.
Also gerade für diese Frage ...
Ziel c:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Schnell:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Natürlich kann dieses Prinzip auf jede Situation angewendet werden, in der Sie sicherstellen möchten, dass eine Änderung nicht animiert wird.
UICollectionView animiert Elemente, nachdem reloadItemsAtIndexPaths aufgerufen wurde (Animation verblassen).
Gibt es eine Möglichkeit, diese Animation zu vermeiden?
iOS 6
Ich gehe davon aus, dass Sie ein FlowLayout verwenden. Versuchen Sie Folgendes, da Sie versuchen, die Überblendungsanimation zu entfernen:
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
}
}
Dies ist eine sehr alte Frage, daher zielen Sie wahrscheinlich nicht mehr auf iOS 6 ab. Ich habe persönlich an tvOS 11 gearbeitet und hatte die gleiche Frage. Dies ist also für alle da, die das gleiche Problem haben.
Ich habe eine Kategorie auf UICollectionView geschrieben , um genau das zu tun. Der Trick besteht darin, alle Animationen beim Neuladen zu deaktivieren:
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
CATransaction.setDisableActions(true)
als Abkürzung tun .
Hier ist eine Swift 3 Version performBatchUpdates
ohne Animation zu einem UICollectionView
. Ich fand, dass dies für mich besser funktioniert, als collectionView.reloadData()
weil es das Austauschen von Zellen beim Einfügen von Datensätzen verringert.
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
})
}
}
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
- (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];
}
}
Um meine $ 0,02 hinzuzufügen, habe ich beide Versionen der ausgewählten Antwort ausprobiert, und die ursprüngliche Methode hat für meine Zwecke besser funktioniert. Ich arbeite an einer unendlichen Bildlauf-Kalenderansicht, mit der ein Benutzer den Kalender zu einer bestimmten Woche eingeben und dann hin und her wischen und einzelne Tage zum Filtern einer Liste auswählen kann.
In meiner Implementierung muss die Anzahl der Daten, die die Kalenderansicht darstellen, relativ klein gehalten werden, um die Leistung auf älteren Geräten zu gewährleisten. Dies bedeutet, dass Daten im Wert von etwa 5 Wochen gespeichert werden, wobei sich der Benutzer in der 3. Woche in der Mitte befindet. Das Problem bei der Verwendung des zweiten Ansatzes besteht darin, dass Sie in einem zweiten Schritt die Sammlungsansicht ohne Animation zurück in die Mitte scrollen müssen, was aus irgendeinem Grund bei der blockierten Basisanimation zu einem sehr gezackten Erscheinungsbild führt.
Mein 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];