如何设置UICollectionView动画的持续时间?

Jam*_*ker 37 grid collectionview ios ios6

我有一个自定义流布局,它正在调整单元格的属性,当它们从CollectionView中插入和删除时具有以下两个函数,但我无法弄清楚如何调整默认动画持续时间.

- (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;
}
Run Code Online (Sandbox Code Playgroud)

zyx*_*xel 28

为了解决gavrix答案中提出的问题, 你可以使用新属性CABasicAnimation *transformAnimation创建UICollectionViewLayoutAttributes子类,而不是创建具有合适持续时间的自定义转换并将其分配给属性initialLayoutAttributesForAppearingItemAtIndexPath,然后在UICollectionViewCell中根据需要应用属性:

@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
Run Code Online (Sandbox Code Playgroud)

在Layout类中

- (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]; 
}
Run Code Online (Sandbox Code Playgroud)

然后在UICollectionViewCell中应用属性

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

  • 您还需要覆盖`+ layoutAttributesClass`以在布局类中返回`[AnimationCollectionViewLayoutAttributes class]`. (6认同)

rot*_*ava 22

改变CALayer的速度

@implementation Cell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
    self.layer.speed =0.2;//default speed  is 1
}
return self;
}
Run Code Online (Sandbox Code Playgroud)

  • 这很有效,很高兴地说.它比其他解决方法更容易.我要补充一点,更高的数字意味着更快的动画. (5认同)

Ash*_*lls 10

在@ rotava的答案的基础上,您可以使用集合视图的批量更新临时设置动画速度:

[self.collectionView performBatchUpdates:^{
    [self.collectionView.viewForBaselineLayout.layer setSpeed:0.2];
    [self.collectionView insertItemsAtIndexPaths: insertedIndexPaths];
} completion:^(BOOL finished) {
    [self.collectionView.viewForBaselineLayout.layer setSpeed:1];
}];
Run Code Online (Sandbox Code Playgroud)


rop*_*cks 5

在尝试[CATransaction setAnimationDuration:][UIView setAnimationDuration:]在布局过程的每个可能阶段都没有成功之后,我想出了一种UICollectionView不依赖私有 API来更改由它创建的单元动画持续时间的有点hacky 的方法。

您可以使用CALayerspeed属性来更改在给定层上执行的动画的相对媒体时间。为此UICollectionView,您可以layer.speed将单元格图层上的值更改为小于 1 的值。显然,让单元格的图层始终具有非统一动画速度并不是很好,因此一种选择是NSNotification在准备单元格动画时分派一个您的单元格订阅的单元格动画,这将更改图层速度,然后将其更改回动画完成后的适当时间。

我不建议使用这种方法作为长期解决方案,因为它非常迂回,但它确实有效。希望 Apple 将来会为 UICollectionView 动画提供更多选项。