你如何设置UICollectionView动画时间?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你如何设置UICollectionView动画时间?相关的知识,希望对你有一定的参考价值。

我有一个自定义流布局时被插入并与以下两个功能从的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;
}
答案

为了不那是你可以继承UICollectionViewLayoutAttributes与新的物业answer by gavrix,比用合适的时间创建自定义转换,并将其分配给CABasicAnimation *transformAnimation属性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

在布局类

- (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]; 
}

然后在UICollectionViewCell应用属性

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

改变的CALayer的速度

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

对@罗塔瓦的回答大厦,您可以暂时使用集合视图的批量更新设置动画速度:

[self.collectionView performBatchUpdates:^{
    [self.collectionView.viewForBaselineLayout.layer setSpeed:0.2];
    [self.collectionView insertItemsAtIndexPaths: insertedIndexPaths];
} completion:^(BOOL finished) {
    [self.collectionView.viewForBaselineLayout.layer setSpeed:1];
}];
另一答案

UICollectionView启动所有动画内部使用一些硬编码值。但是,你总是可以覆盖该值,直到动画承诺。在一般情况下,过程是这样的:

  • 开始动画
  • 获取所有布局属性
  • 将属性应用于意见(UICollectionViewCell的)
  • 提交动画

应用属性是每个UICollectionViewCell下完成的,你可以在适当的方法来覆盖animationDuration。问题是,UICollectionViewCell具有公共方法applyLayoutAttributes:但它的默认的实现是空的!基本上,UICollectionViewCell有其它的私有方法称为_setLayoutAttributes:这种私有方法被称为UICollectionView这种私有方法在结束通话applyLayoutAttributes:。默认布局属性,像帧,位置与当前的animationDuration施加变换applyLayoutAttributes:被调用之前。这就是说,你在私有方法animationDuration覆盖_setLayoutAttributes:

- (void) _setLayoutAttributes:(PSTCollectionViewLayoutAttributes *)layoutAttributes
{
    [UIView setAnimationDuration:3.0];
    [super _setLayoutAttributes:layoutAttributes];
}

这显然不是的AppleStore安全。您可以使用这些运行黑客的一个安全地覆盖这个私有方法。

另一答案

在没有成功布局过程的每一个可能的相位试图[CATransaction setAnimationDuration:][UIView setAnimationDuration:]后,我想出了一个有点哈克的方式来改变由不依赖于私有API的UICollectionView创建细胞动画的持续时间。

您可以使用CALayerspeed属性来改变给定层上进行动画的相对的媒体时间。对于这个与UICollectionView工作,你可以layer.speed改变细胞的层上的东西小于1。显然,这不是伟大的,有细胞的层始终有一个非统一动画的速度,所以其中一个方案是派遣细胞动画制作时NSNotification,你的细胞的认同,这将改变层的速度,然后再改回来在适当的时间之后,动画完成。

我不推荐使用这种方法作为一个长期的解决方案,这是很迂回,但它确实工作。希望苹果将暴露在未来UICollectionView动画更多的选择。

另一答案

您可以设置图层的速度属性(如在Rotoava's Answer)改变控制动画的速度。问题是你正在使用任意值,因为你不知道插入动画的实际工期。

使用this post你可以找出默认的动画时间是什么。

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;
}
另一答案

没有子分类:

[UIView animateWithDuration:2.0 animations:^{
  [self.collection reloadSections:indexSet];
}];
另一答案

因为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
})
另一答案

你可以改变UICollectionView layout.speed财产,应改变布局的动画时长...

以上是关于你如何设置UICollectionView动画时间?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用持续时间为单个 UICollectionView 单元格设置动画

使用 UIDynamics Swift 为 UICollectionView 设置动画

如何更改自定义 UICollectionView 布局引擎中的默认布局动画曲线?

UICollectionVIew:在滚动时为单元格设置动画

UICollectionView.scrollToItem 设置动画速度

为 UICollectionView 中的所有 UICollectionViewCell 设置动画