iosios6gridcollectionview

How do you set the duration for UICollectionView Animations?


I have a custom flow layout which is adjusting the attributes for cells when they are being inserted and deleted from the CollectionView with the following two functions, but I'm unable to figure out how you would adjust the default animation duration.

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
    UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];

    // Assign the new layout attributes
    attributes.transform3D = CATransform3DMakeScale(0.5, 0.5, 0.5);
    attributes.alpha = 0;

    return attributes;
}

- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {

    UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];

    // Assign the new layout attributes
    attributes.transform3D = CATransform3DMakeScale(0.5, 0.5, 0.5);
    attributes.alpha = 0;

    return attributes;
}

Solution

  • To solve problem without hack that was proposed in the answer by gavrix you could subclass UICollectionViewLayoutAttributes with new property CABasicAnimation *transformAnimation, than create custom transformation with a suitable duration and assign it to attributes in initialLayoutAttributesForAppearingItemAtIndexPath, then in UICollectionViewCell apply the attributes as needed:

    @interface AnimationCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes
    @property (nonatomic, strong)  CABasicAnimation *transformAnimation;
    @end
    
    @implementation AnimationCollectionViewLayoutAttributes
    - (id)copyWithZone:(NSZone *)zone
    {
        AnimationCollectionViewLayoutAttributes *attributes = [super copyWithZone:zone];
        attributes.transformAnimation = _transformAnimation;
        return attributes;
    }
    
    - (BOOL)isEqual:(id)other {
        if (other == self) {
            return YES;
        }
        if (!other || ![[other class] isEqual:[self class]]) {
            return NO;
        }
        if ([(( AnimationCollectionViewLayoutAttributes *) other) transformAnimation] != [self transformAnimation]) {
            return NO;
        }
    
        return YES;
    }
    @end
    

    In Layout class

    - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
        AnimationCollectionViewLayoutAttributes* attributes = (AnimationCollectionViewLayoutAttributes* )[super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
    
        CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
        transformAnimation.duration = 1.0f;
        CGFloat height = [self collectionViewContentSize].height;
    
        transformAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, 2*height, height)];
        transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, attributes.bounds.origin.y, 0)];
        transformAnimation.removedOnCompletion = NO;
        transformAnimation.fillMode = kCAFillModeForwards;
        attributes.transformAnimation = transformAnimation;
        return attributes;
    }
    
    + (Class)layoutAttributesClass { 
        return [AnimationCollectionViewLayoutAttributes class]; 
    }
    

    then in UICollectionViewCell apply the attributes

    - (void) applyLayoutAttributes:(AnimationCollectionViewLayoutAttributes *)layoutAttributes
    {
        [[self layer] addAnimation:layoutAttributes.transformAnimation forKey:@"transform"];
    }