UICollectionView, reloadItemsAtIndexPaths çağrıldıktan sonra öğelere animasyon uygulayın (fade animation).
Bu animasyondan kaçınmanın bir yolu var mı?
iOS 6
Yanıtlar:
İOS 7 ve üstünü hedefliyorsanız, yeni UIView
yöntemi kullanabileceğinizi belirtmek gerekir performWithoutAnimation:
. Başlık altında bunun buradaki diğer cevaplarla aynı şeyi yaptığından şüpheleniyorum ( UIView
animasyonları geçici olarak devre dışı bırakma / Temel Animasyon eylemleri), ancak sözdizimi güzel ve temiz.
Yani özellikle bu soru için ...
Amaç-C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Swift:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Tabii bu ilke, bir değişiklik sağlamak istediğiniz her durum için uygulanabilir değildir animasyonlu.
Şunu da deneyebilirsiniz:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
Ayrıca performBatchUpdates
, bir UIView animasyon bloğunu sararsanız, varsayılan animasyon yerine UIView animasyonunun kullanıldığını, böylece animasyon süresini 0 olarak ayarlayabileceğinizi buldum , örneğin:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
Ekleme ve silme işlemleri sırasında iOS 7 yaylı animasyonlarını kullanmak istiyorsanız bu çok harika!
performBatchUpdates
İçini sarmak animateWithDuration
harika! Bahşiş için teşekkürler!
UICollectionView, reloadItemsAtIndexPaths çağrıldıktan sonra öğelere animasyon uygulayın (fade animation).
Bu animasyondan kaçınmanın bir yolu var mı?
iOS 6
FlowLayout kullandığınızı varsayıyorum. Solma animasyonundan kurtulmaya çalıştığınız için şunu deneyin:
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
}
}
Bu çok eski bir soru, bu yüzden muhtemelen artık iOS 6'yı hedeflemiyorsunuz. Ben şahsen tvOS 11 üzerinde çalışıyordum ve aynı soruyu sormuştum, yani bu, aynı problemle gelen herkes için burada.
Bunu yapmak için UICollectionView'da bir kategori yazdım . İşin püf noktası, yeniden yüklerken tüm animasyonları devre dışı bırakmaktır:
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
CATransaction.setDisableActions(true)
için bir kısaltma olarak da yapabilirsiniz .
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
İşte bir Swift 3 sürümü performBatchUpdates
animasyonsuz bir UICollectionView
. collectionView.reloadData()
Kayıtlar eklendiğinde hücre değişimini azalttığı için bunun benim için daha iyi çalıştığını gördüm .
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];
}
}
Sadece 0,02 doları eklemek için, seçilen cevabın her iki versiyonunu da denedim ve orijinal yöntem amaçlarım için daha iyi çalıştı. Bir kullanıcının belirli bir haftada takvime girmesine ve ardından ileri geri kaydırıp bir listeyi filtrelemek için tek tek günleri seçmesine olanak tanıyan sonsuz bir kaydırmalı takvim görünümü üzerinde çalışıyorum.
Benim uygulamamda, eski cihazlarda işlerin daha iyi performans göstermesini sağlamak için, takvim görünümünü temsil eden tarih dizisinin nispeten küçük tutulması gerekiyor, bu da kullanıcı 3. haftada ortada olacak şekilde yaklaşık 5 hafta değerinde tarih tutmak anlamına geliyor. İkinci yaklaşımı kullanmakla ilgili sorun, koleksiyon görünümünü bir animasyon olmadan tekrar ortaya kaydırmanız gereken ikinci bir adımdır, bu da engellenen temel animasyonla bir nedenden ötürü çok pürüzlü bir görünüm sağlar.
Kodum:
[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)
}