[ios] 你如何设置UICollectionView动画的持续时间?



Answers

改变CALayer的速度

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

我有一个自定义的流布局,正在调整单元格的属性,当他们被插入和从以下两个函数从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;

}




在布局过程的每个可能阶段尝试了[CATransaction setAnimationDuration:][UIView setAnimationDuration:]之后,我想出了一个有点不好的方法来改变由UICollectionView创建的细胞动画的持续时间,而不依赖于私有API。

您可以使用CALayerspeed属性来更改给定图层上执行的动画的相对媒体时间。 为了与UICollectionView一起工作,可以在单元图层layer.speed更改为小于1的值。 很明显,单元格的层总是具有非统一的动画速度并不是很好,所以有一种选择是在准备单元格动画的时候发送一个NSNotification ,这个单元格动画会改变图层的速度,然后改变它的速度在动画结束后的适当的时候。

我不建议使用这种方法作为一个长期的解决方案,因为它非常迂回,但它确实有效。 希望苹果未来能够为UICollectionView动画提供更多的选择。




你可以设置图层的速度属性(如[Rotoava's Answer])( https://.com/a/23146861/5271393 )来改变控制动画的速度。 问题是你使用的是任意值,因为你不知道插入动画的实际持续时间。

使用这个帖子你可以找出什么是默认的动画持续时间。

newAnimationDuration = (1/layer.speed)*originalAnimationDuration
layer.speed = originalAnimationDuration/newAnimationDuration

如果你想制作长达400ms的动画,在你的布局中你可以:

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewLayoutAttributes* attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:indexPath];
    //set attributes here
    UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
    CGFloat originalAnimationDuration = [CATransaction animationDuration];
    CGFloat newAnimationDuration = 0.4f;
    cell.layer.speed = originalAnimationDuration/newAnimationDuration;
    return attributes;
}

在我的情况下,我有可能被拖出屏幕的单元格,我想根据平移手势的速度更改删除动画的持续时间。

在手势识别器(这应该是你的集合视图的一部分):

- (void)handlePanGesture:(UIPanGestureRecognizer *)sender
{
    CGPoint dragVelocityVector = [sender velocityInView:self.collectionView];
    CGFloat dragVelocity = sqrt(dragVelocityVector.x*dragVelocityVector.x + dragVelocityVector.y*dragVelocityVector.y);
    switch (sender.state) {
    ...
    case UIGestureRecognizerStateChanged:{
        CustomLayoutClass *layout = (CustomLayoutClass *)self.collectionViewLayout;
        layout.dragSpeed = fabs(dragVelocity);
    ...
    }
    ...
}

然后在你的customLayout中:

- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewLayoutAttributes* attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:indexPath];
    CGFloat animationDistance = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
    CGFloat originalAnimationDuration = [CATransaction animationDuration];
    CGFloat newAnimationDuration = animationDistance/self.dragSpeed;
    UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
    cell.layer.speed = originalAnimationDuration/newAnimationDuration;
    return attributes;
}



自从forBaselineLayout以来,对@AshleyMills的更新已被弃用

这工作

self.collectionView.performBatchUpdates({ () -> Void in
      let indexSet = IndexSet(0...(numberOfSections - 1))
      self.collectionView.insertSections(indexSet)
      self.collectionView.forFirstBaselineLayout.layer.speed = 0.5
} , completion: { (finished) -> Void in
      self.collectionView.forFirstBaselineLayout.layer.speed = 1.0
})





Related