UICollectionView : animation custom layout

2019-02-03 18:35发布

问题:

I'm displaying lots of image cells in an UICollectionView. With one button I would like to be able to group all my cell over the first one.

This is working well but when I'm trying to add an animation transition to my regroup action, nothing happens.

Here the method I use in a custom layout :

- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray* allAttributesInRect = [super layoutAttributesForElementsInRect:rect];

    if([allAttributesInRect count] > 0 && _isRegroup)
    {
        UICollectionViewLayoutAttributes *firstAttribute = [allAttributesInRect objectAtIndex:0];
        CGRect frame = firstAttribute.frame;

        for(UICollectionViewLayoutAttributes *attribute in allAttributesInRect)
            [UIView animateWithDuration:0.3f animations:^{attribute.frame = frame;}];
    }
    return allAttributesInRect;
}

- (void)regroupCells:(BOOL)isRegroup // This method is called from my collection controller when my button is pressed
{
    _isRegroup = isRegroup;
    [self invalidateLayout];
}

Any idea ? Thanks !

回答1:

Animations won't work from within the method you are calling them from.

To change the layout and animate to a new one, the simplest method is to call performBatchUpdates on your collection view, with nil for each block parameter. This invalidates your layout and animates to the new one for you.

Before doing this, you'd tell the layout object that you want the new layout to occur. Also, inside layoutAttributesForElementsInRect, simply check your Boolean variable and apply the grouped frame (probably center would be better) to all attributes as you are doing now, but without animation. You'll also need to reproduce this code in layoutAttributesForElementAtIndexPath.

So, in summary:

  1. Remove your invalidate layout call from where it is
  2. Remove the animation calls from where they are, just amend the layout attributes
  3. Add ..forElementAtIndexPath code as well
  4. In your view controller, call the regroup method on the layout object, then call performBatchupdates on the collection view.