ios 在 reloadItemsAtIndexPaths 后避免 UICollectionView 的动画
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14094684/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Avoid animation of UICollectionView after reloadItemsAtIndexPaths
提问by Marcin
UICollectionView animate items after reloadItemsAtIndexPaths is called (fade animation).
UICollectionView 在 reloadItemsAtIndexPaths 被调用后动画项目(淡入淡出动画)。
Is there a way to avoid this animation?
有没有办法避免这个动画?
iOS 6
iOS 6
回答by Stuart
It's worth noting that if you're targeting iOS 7 and above, you can use the new UIView
method performWithoutAnimation:
. I suspect that under the hood this is doing much the same as the other answers here (temporarily disabling UIView
animations / Core Animation actions), but the syntax is nice and clean.
值得注意的是,如果您的目标是 iOS 7 及更高版本,则可以使用新UIView
方法performWithoutAnimation:
。我怀疑在幕后,这与此处的其他答案大致相同(暂时禁用UIView
动画/核心动画操作),但语法很好且干净。
So for this question in particular...
所以对于这个问题,特别...
Objective-C:
目标-C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Swift:
迅速:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Of course this principle can be applied for any situation that you want to ensure a change is notanimated.
当然,这个原则可以应用于任何您想要确保更改不是动画的情况。
回答by Sam
You could also try this:
你也可以试试这个:
UICollectionView *collectionView;
...
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
Edit:
编辑:
I have also found that if you wrap performBatchUpdates
in a UIView animation block, the UIView animation is used instead of the default animation, so you can just set the animation duration to 0, like so:
我还发现,如果你包裹performBatchUpdates
在 UIView 动画块中,则使用 UIView 动画而不是默认动画,因此你可以将动画持续时间设置为 0,如下所示:
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
This is extra cool if you want to use iOS 7 springy animations during inserts and deletes!
如果您想在插入和删除期间使用 iOS 7 弹性动画,这将非常酷!
回答by Matt Mc
UICollectionView animate items after reloadItemsAtIndexPaths is called (fade animation).
Is there a way to avoid this animation?
iOS 6
UICollectionView 在 reloadItemsAtIndexPaths 被调用后动画项目(淡入淡出动画)。
有没有办法避免这个动画?
iOS 6
I assume you're using a FlowLayout. Since you're trying to get rid of the fade animation, try this:
我假设您使用的是 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
}
}
This is a very old question, so you're probably not targeting iOS 6 anymore. I was personally working on tvOS 11 and had the same question, so this is here for anyone who comes along with the same problem.
这是一个非常古老的问题,因此您可能不再针对 iOS 6。我个人在 tvOS 11 上工作并有同样的问题,所以这里适合遇到同样问题的任何人。
回答by Giorgio Calderolla
I wrote a category on UICollectionViewto do just that. The trick is to disable all animations while reloading:
我在 UICollectionView 上写了一个类别来做到这一点。诀窍是在重新加载时禁用所有动画:
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
回答by markhorrocks
Here is a Swift 3 version to performBatchUpdates
without animation to a UICollectionView
. I found this to work better for me than collectionView.reloadData()
because it reduced cell swapping when records were inserted.
这是一个 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
})
}
}
回答by Amjad Tubasi
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
回答by Peter Lapisu
- (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];
}
}
回答by Matt S.
Just to add my $0.02, I tried both versions of the selected answer, and the original way worked better for my purposes. I am working on an infinite scrolling calendar view that allows for a user to enter the calendar at a given week and then swipe back and forth and select individual days for filtering a list.
只是为了增加我的 0.02 美元,我尝试了所选答案的两个版本,原始方法更适合我的目的。我正在开发一个无限滚动的日历视图,它允许用户在给定的一周输入日历,然后来回滑动并选择个别日期来过滤列表。
In my implementation, in order to keep things performant on older devices the array of dates that represent the calendar view has to be kept relatively small which means holding about 5 weeks worth of dates, with the user in the middle at the 3rd week. The issue with using the second approach is, there's a second step where you have to scroll the collection view back to the middle without an animation, which makes for a very jagged appearance for some reason with the blocked base animation.
在我的实现中,为了在旧设备上保持性能,代表日历视图的日期数组必须保持相对较小,这意味着保留大约 5 周的日期,用户在第 3 周处于中间。使用第二种方法的问题是,在第二个步骤中,您必须在没有动画的情况下将集合视图滚动回中间,这会由于某种原因与被阻止的基本动画产生非常锯齿状的外观。
My 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];