How do you set the duration for UICollectionView Animations?

后端 未结 9 2077
旧巷少年郎
旧巷少年郎 2020-12-12 17:07

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, bu

9条回答
  •  盖世英雄少女心
    2020-12-12 17:38

    You can set the layer's speed property (like in Rotoava's Answer) to change the control the speed of the animation. The problem is you are using arbitrary values because you do not know the actual duration of the insertion animation.

    Using this post you can figure out what the default animation duration is.

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

    If you wanted to make the animation 400ms long, in your layout you would:

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

    In my case I had cells which could be dragged off screen and I wanted to change the duration of the deletion animation based on the speed of the pan gesture.

    In the gesture recognizer (which should be part of your collection view):

    - (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);
        ...
        }
        ...
    }
    

    Then in your 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;
    }
    

提交回复
热议问题