Викликається анімовані елементи UICollectionView після reloadItemsAtIndexPaths (анімація затухання).
Чи є спосіб уникнути цієї анімації?
iOS 6
Відповіді:
Варто зазначити, що якщо ви націлюєтесь на iOS 7 і новіших версій, ви можете використовувати новий UIView
метод performWithoutAnimation:
. Я підозрюю, що під капотом це робить майже те саме, що й інші відповіді тут (тимчасово відключаючи UIView
анімацію / дії основної анімації), але синтаксис приємний і чистий.
Тож щодо цього питання зокрема ...
Завдання-C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Стрімкий:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Звичайно, цей принцип можна застосовувати до будь-якої ситуації, для якої ви хочете, щоб зміни не анімувались.
Ви також можете спробувати це:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
Я також виявив, що якщо ви загортаєте performBatchUpdates
в блок анімації UIView, замість анімації за замовчуванням використовується анімація UIView, тому ви можете просто встановити тривалість анімації на 0, наприклад:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
Це дуже круто, якщо ви хочете використовувати пружну анімацію iOS 7 під час вставки та видалення!
performBatchUpdates
всередину animateWithDuration
- блискуче! Дякуємо за підказку!
Викликається анімовані елементи UICollectionView після reloadItemsAtIndexPaths (анімація затухання).
Чи є спосіб уникнути цієї анімації?
iOS 6
Я припускаю, що ви використовуєте FlowLayout. Оскільки ви намагаєтеся позбутися загасання анімації, спробуйте наступне:
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
}
}
Це дуже давнє запитання, тому ви, мабуть, більше не націлюєте iOS 6. Я особисто працював над tvOS 11 і мав те саме запитання, тому це тут для тих, хто стикається з тією ж проблемою.
Я написав категорію на UICollectionView, щоб зробити саме це. Фокус полягає у відключенні всіх анімацій під час перезавантаження:
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
CATransaction.setDisableActions(true)
як скорочення.
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
Ось версія Swift 3 до performBatchUpdates
без анімації до UICollectionView
. Я виявив, що це працює для мене краще, ніж collectionView.reloadData()
тому, що це зменшило обмін клітинками, коли вставлялися записи.
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];
}
}
Просто щоб додати свої 0,02 долара, я спробував обидві версії вибраної відповіді, і оригінальний спосіб працював краще для моїх цілей. Я працюю над нескінченним прокручуваним поданням календаря, яке дозволяє користувачеві вводити календар у певний тиждень, а потім проводити пальцем вперед і назад та вибирати окремі дні для фільтрування списку.
У моїй реалізації, щоб підтримувати ефективність роботи на старих пристроях, масив дат, що представляє подання календаря, повинен бути відносно невеликим, що означає тримати дати приблизно на 5 тижнів, а користувач посередині на 3-му тижні. Проблема з використанням другого підходу полягає в тому, що є другий крок, коли вам потрібно прокрутити подання колекції назад до середини без анімації, що робить дуже зазубреним вигляд чомусь із заблокованою базовою анімацією.
Мій код:
[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)
}