Avoid animation of UICollectionView after reloadItemsAtIndexPaths

76,422

Solution 1

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.

So for this question in particular...

Objective-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 not animated.

Solution 2

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:

[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!

Solution 3

UICollectionView animate items after reloadItemsAtIndexPaths is called (fade animation).

Is there a way to avoid this animation?

iOS 6

I assume you're using a FlowLayout. Since you're trying to get rid of the fade animation, try this:

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.

Solution 4

I wrote a category on UICollectionView to do just that. The trick is to disable all animations while reloading:

if (!animated) {
    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}

[self reloadItemsAtIndexPaths:indexPaths];

if (!animated) {
    [CATransaction commit];
}

Solution 5

extension UICollectionView {
    func reloadWithoutAnimation(){
        CATransaction.begin()
        CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
        self.reloadData()
        CATransaction.commit()
    }
}
Share:
76,422
Marcin
Author by

Marcin

Passionate developer. iOS. https://github.com/krzyzanowskim

Updated on July 08, 2022

Comments

  • Marcin
    Marcin almost 2 years

    UICollectionView animate items after reloadItemsAtIndexPaths is called (fade animation).

    Is there a way to avoid this animation?

    iOS 6

  • Marcin
    Marcin over 11 years
    I also get response from Apple that this should not do any animation, if so it's a bug. I don't know if I'm doing something wrong or it's a bug.
  • hatunike
    hatunike about 11 years
    Thank you. This was very helpful in adding stopwatch timers to uicollectionview cells.
  • David H
    David H over 10 years
    Brilliant! I used this with insertCells, and with the keyboard up, to animate the collectionView to a new offset after the cell was inserted.
  • Peter Lapisu
    Peter Lapisu over 10 years
    conflicts with other animations :/
  • Adlai Holler
    Adlai Holler over 10 years
    As Peter says, this interferes with other animations. Instead, you should call [UIView setAnimationsEnabled:YES] outside of the completion block. That way you only prevent that 1 animation.
  • Sam
    Sam about 10 years
    I added an alternative method, which does exactly the same thing.
  • Robert
    Robert over 9 years
    Wrapping performBatchUpdates inside animateWithDuration is brilliant! Thanks for the tip!
  • Philippe Sabourin
    Philippe Sabourin over 9 years
    This worked better than the accepted answer for me on iOS 7+.
  • user2159978
    user2159978 over 9 years
    WARNING. This method DOESN'T WORK PROPERLY!!! Try to scroll while this method is executed. At least in my case when I should reload layout too it breaks content size of collection view
  • user2159978
    user2159978 over 9 years
    It disables all the animations not only for collection view
  • Stuart
    Stuart over 9 years
    @user2159978 That's correct; all the answers here temporarily disable UIView animations. The animations are only disabled for actions initiated from within the passed-in block, in this case just the collection view's reload. It is a perfectly valid answer to the question being asked, so I don't think it deserves a down vote.
  • BollMose
    BollMose over 8 years
    I don't know why but it's perfectly fix my flashing issue with UIView animateWithDuration:0 animations. Thank you very much.
  • Magoo
    Magoo about 8 years
    Second one is much safer! :)
  • Just a coder
    Just a coder almost 8 years
    Visually, the second method does not work as well as the first method.
  • Amjad Tubasi
    Amjad Tubasi over 7 years
    this is swift 3 syntax
  • CIFilter
    CIFilter about 7 years
    You can also just do CATransaction.setDisableActions(true) as a shorthand for this.
  • Ethan Gill
    Ethan Gill over 6 years
    Incredible solution. Using this instead of animateWithDuration:0 prevents a quick but visible layout glitch when using self-sizing collection view cells with no itemSize
  • Matt Mc
    Matt Mc almost 5 years
    There were 3 or 4 comments on this answer to the effect of "Wow this works really well!" Someone decided to remove the comments. I think, factually, this is the modern and non-hacky way of accomplishing this, and those comments were a recognition of this.
  • Lance Samaria
    Lance Samaria almost 4 years
    this worked good, even better than UIView.performWithoutAnimation
  • Maray97
    Maray97 over 3 years
    This solution doesn't work anymore on iOS 14, inside this block I use reloadData, but with iOS 13 it worked