UICollectionView animations (insert/delete items)

41,508

Solution 1

If you use your own subclass of UICollectionViewLayout, you can implement the methods:

  • initialLayoutAttributesForAppearingItemAtIndexPath: for insertions

  • finalLayoutAttributesForDisappearingItemAtIndexPath: for deletions

According to the documentation, the attributes you return are used as starting points for the animation, and the end point are the normal attributes returned by your layout (or the opposite for deletion). Layout attributes include position, alpha, transform... Of course, it is more work to write your own layout class than to use the Apple provided flow layout.

Edit: To answer your question in the comments, here is a super basic implementation of a layout for rows of items which are all the same size.

A cell has a frame and, by default, an alpha of 1.0 (as defined by layoutAttributesForItemAtIndexPath:). When it is deleted, its properties will be animated from its current state before the deletion to the properties set by finalLayoutAttributesForDisappearingItemAtIndexPath:, which correspond to the same frame and an alpha of 0.0. So it won't move but it will fade out. However, the cells to the right are going to be moved to the left (because their indexPath has changed, and thus their frame as set by layoutAttributesForItemAtIndexPath:).

- (CGSize)collectionViewContentSize
{
    NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:0];
    return CGSizeMake(numberOfItems * ITEM_WIDTH, ITEM_HEIGHT);
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger index = [indexPath indexAtPosition:0];
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    attributes.frame = CGRectMake(index * ITEM_WIDTH, 0, ITEM_WIDTH, ITEM_HEIGHT);
    return attributes;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray *attributes = [NSMutableArray new];
    NSUInteger firstIndex = floorf(CGRectGetMinX(rect) / ITEM_WIDTH);
    NSUInteger lastIndex = ceilf(CGRectGetMaxX(rect) / ITEM_WIDTH);
    for (NSUInteger index = firstIndex; index <= lastIndex; index++) {
        NSIndexPath *indexPath = [[NSIndexPath alloc] initWithIndexes:(NSUInteger [2]){ 0, index } length:2];
        [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
    }
    return attributes;
}

- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
    attributes.alpha = 0.0;
    return attributes;
}

Solution 2

Download the circle Layout. It is a sample custom layout that using

initialLayoutAttributesForAppearingItemAtIndexPath:  
finalLayoutAttributesForDisappearingItemAtIndexPath:  

That will be a good working material for you.

Share:
41,508

Related videos on Youtube

Sergey Katranuk
Author by

Sergey Katranuk

Updated on May 23, 2020

Comments

  • Sergey Katranuk
    Sergey Katranuk almost 4 years

    I'd like to customize the animation styles when a UICollectionViewCell is inserted and/or deleted.

    The reason why I need this is that by default I see that inserting a cell has a smooth fade in animation, however deleting a cell has a combination of move-to-the-left + fade out animation. I would be very happy with this if not for one problem.

    After I delete a cell, it is still reused when I add new ones, and when it's reused it's added not with the default fade in effect, but instead it's a combination of move-to-the-left + fade in.

    I'm not sure why I'm getting this inconsistency in animations. If this is a known bug/problem/stupidity(on my side :)) please let me know how to fix it.

    Otherwise, let me know how to set custom animations when the cell is deleted (or point me towards a tutorial).

    Thanks

    UPDATE

    Fixed the weird animation behavior by subclassing UICollectionViewFlowLayout and adding this line of code

    - (UICollectionViewLayoutAttributes *) initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
    
          return nil;
    }
    

    That's it! :)

    • Ely
      Ely over 5 years
      According the documentation the result for initialLayoutAttributesForAppearingItemAtIndexPath is already nil.
  • Sergey Katranuk
    Sergey Katranuk almost 11 years
    Thanks Guillaume. But, could you give me a concrete example? Let's say I want to make sure that my cell just fades out when it is deleted, how do I implement that in my custom UICollectionViewLayout?
  • Guillaume
    Guillaume almost 11 years
    I added an example in answer to your question.