在调用reloadItemsAtIndexPaths方法后,如何对UICollectionView中的项目进行动画(淡入淡出)?是否有避免这种动画的方法?iOS 6。
UIView
方法 performWithoutAnimation:
。我怀疑在幕后执行的操作与其他答案(暂时禁用 UIView
动画 / 核心动画操作)相同,但语法简洁明了。[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Swift:
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];
}];
performBatchUpdates
包裹在animateWithDuration
中是太棒了!感谢这个技巧! - Robert在调用reloadItemsAtIndexPaths后,UICollectionView中的项目进行动画处理(淡入淡出动画)。
有没有办法避免这种动画效果?
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)
作为这个过程的简写。 - CIFilterextension 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];
}
}
[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];
不要使用reloadData()
,尝试以下方法重新加载所有可见单元格而不带动画。
self.collectionView.reloadItems(at: self.collectionView.indexPathsForVisibleItems)
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)
}