UICollectionView menganimasikan item setelah reloadItemsAtIndexPaths dipanggil (animasi fade).
Adakah cara untuk menghindari animasi ini?
iOS 6
Jawaban:
Perlu dicatat bahwa jika Anda menargetkan iOS 7 ke atas, Anda dapat menggunakan UIView
metode baru performWithoutAnimation:
. Saya menduga bahwa di bawah tenda ini melakukan hal yang sama dengan jawaban lain di sini (sementara menonaktifkan UIView
animasi / tindakan Animasi Inti), tetapi sintaksnya bagus dan bersih.
Jadi untuk pertanyaan ini khususnya ...
Objective-C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Cepat:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Tentu saja prinsip ini dapat diterapkan untuk situasi apa pun yang Anda inginkan untuk memastikan perubahan tidak dianimasikan.
Anda juga bisa mencoba ini:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
Saya juga menemukan bahwa jika Anda membungkus performBatchUpdates
dalam blok animasi UIView, animasi UIView digunakan sebagai pengganti animasi default, jadi Anda bisa mengatur durasi animasi ke 0, seperti:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
Ini sangat keren jika Anda ingin menggunakan animasi kenyal iOS 7 selama memasukkan dan menghapus!
performBatchUpdates
bagian dalam animateWithDuration
itu brilian! Terima kasih atas tipnya!
UICollectionView menganimasikan item setelah reloadItemsAtIndexPaths dipanggil (animasi fade).
Adakah cara untuk menghindari animasi ini?
iOS 6
Saya berasumsi Anda menggunakan FlowLayout. Karena Anda mencoba menghilangkan animasi pudar, coba ini:
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
}
}
Ini adalah pertanyaan yang sangat lama, jadi Anda mungkin tidak menargetkan iOS 6 lagi. Saya secara pribadi bekerja di tvOS 11 dan memiliki pertanyaan yang sama, jadi ini di sini untuk siapa saja yang datang dengan masalah yang sama.
Saya menulis kategori di UICollectionView untuk melakukan hal itu. Triknya adalah menonaktifkan semua animasi saat memuat ulang:
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
CATransaction.setDisableActions(true)
sebagai singkatan untuk ini.
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
Ini adalah versi Swift 3 performBatchUpdates
tanpa animasi ke UICollectionView
. Saya menemukan ini bekerja lebih baik untuk saya daripada collectionView.reloadData()
karena mengurangi pertukaran sel saat rekaman dimasukkan.
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];
}
}
Hanya untuk menambahkan $ 0,02 saya, saya mencoba kedua versi jawaban yang dipilih, dan cara asli bekerja lebih baik untuk tujuan saya. Saya sedang mengerjakan tampilan kalender gulir tak terbatas yang memungkinkan pengguna untuk masuk ke kalender pada minggu tertentu dan kemudian menggesek bolak-balik dan memilih hari individu untuk memfilter daftar.
Dalam implementasi saya, untuk menjaga agar segala sesuatunya berjalan dengan baik pada perangkat yang lebih lama, susunan tanggal yang mewakili tampilan kalender harus dijaga agar relatif kecil yang berarti memegang tanggal sekitar 5 minggu, dengan pengguna di tengah pada minggu ke-3. Masalah dengan menggunakan pendekatan kedua adalah, ada langkah kedua di mana Anda harus menggulir tampilan koleksi kembali ke tengah tanpa animasi, yang membuat tampilan sangat bergerigi karena beberapa alasan dengan animasi dasar yang diblokir.
Kode Saya:
[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)
}