What is the relationship between bounds.size and frame.size when animating a UICollectionViewCell

I read a few posts (e.g., https://stackoverflow.com/a/312620/... and https://stackoverflow.com/a/3129478/ ), that resizing a UIView with animation, we cannot animate the frame, and we have to do it with using a combination of bounds.size, bounds.origin and position.

However, I cannot find what the correlation between these properties and frame properties is.

I have a UICollectionView with a custom layout. When a cell is deleted, the layout is updated, and each cell receives its new frame using the prepareLayoutand methods layoutAttributesForElementsInRect:. Then the method is called finalizeCollectionViewUpdates(where we can edit the animation), and finally, the cells move and change.

I did a lot of trial and error research with cell animations, and here is what I found:

  • 3 animations are by default set by my visible cells which are position, bounds.origin and bounds.size
  • when I change the values ​​from / to the values ​​of these animations, only the position of the POSITION cell is affected, and never its SIZE

Detailed Results

Default values

When I use the default values ​​for animations and check their values ​​with these logs,

- (void)finalizeCollectionViewUpdates {
    for(UICollectionViewCell* cell in [self.collectionView visibleCells]) {
        NSLog(@"cell: %@", cell);
        for(NSString* key in cell.layer.animationKeys) {
            CABasicAnimation* animation = (CABasicAnimation*)[cell.layer animationForKey:key];
            NSLog(@"animation %@: from %@ to %@", key, animation.fromValue, animation.toValue);
        }
    }
}

I get this for the reduction cell (its frame represents its final state):

cell: <PlayQueueSongCell: 0x7fbf1bc8ebe0; baseClass = UICollectionViewCell; frame = (53.3333 80; 480 480); opaque = NO; animations = { position=<CABasicAnimation: 0x7fbf1bf54e20>; bounds.origin=<CABasicAnimation: 0x7fbf1bf556b0>; bounds.size=<CABasicAnimation: 0x7fbf1bf557a0>; }; layer = <CALayer: 0x7fbf1bc8e9f0>>
animation position: from NSPoint: {666.66666666666674, 0} to NSPoint: {0, 0}
animation bounds.origin: from NSPoint: {0, 0} to NSPoint: {0, 0}
animation bounds.size: from NSSize: {160, 160} to NSSize: {0, 0}

and this is for the cell expating (its frame represents its final state):

cell: <PlayQueueSongCell: 0x7fbf1bd6cd00; baseClass = UICollectionViewCell; frame = (640 0; 640 640); opaque = NO; animations = { position=<CABasicAnimation: 0x7fbf1bf55b70>; bounds.origin=<CABasicAnimation: 0x7fbf1bf55e20>; bounds.size=<CABasicAnimation: 0x7fbf1bf55f10>; }; layer = <CALayer: 0x7fbf1bd73200>>
animation position: from NSPoint: {666.66666666666652, 0} to NSPoint: {0, 0}
animation bounds.origin: from NSPoint: {0, 0} to NSPoint: {0, 0}
animation bounds.size: from NSSize: {-160, -160} to NSSize: {0, 0}

See the result in slow motion: enter image description here

No bounds.size animation

When I remove the bounds.size animation with this code block,

- (void)finalizeCollectionViewUpdates {
    for(UICollectionViewCell* cell in [self.collectionView visibleCells]) {
        for(NSString* key in cell.layer.animationKeys) {
            [cell.layer removeAnimationForKey:@"bounds.size"];
        }
    }
}

I see that only the POSITION of the cell is affected ... enter image description here

bounds.size (0,0) (1000,1000)

bounds.size (0,0) → (1000,1000) :

- (void)finalizeCollectionViewUpdates {
    for(UICollectionViewCell* cell in [self.collectionView visibleCells]) {
        for(NSString* key in cell.layer.animationKeys) {
            [cell.layer removeAnimationForKey:@"bounds.size"];
            CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
            [animation setFromValue:[NSValue valueWithCGSize:CGSizeZero]];
            [animation setToValue:[NSValue valueWithCGSize:CGSizeMake(1000, 1000)]];
            [animation setDuration:0.3];
            [cell.layer addAnimation:animation forKey:@"bounds.size"];
        }
    }
}

, POSITION ... enter image description here

, bounds.size , .

bounds.size frame.size, , ?

+4
1

, , - bounds.size, . transform.scale, , 1.

if([cell.layer animationForKey:@"bounds.size"]) {
    [cell.layer removeAnimationForKey:@"bounds.size"];

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    animation.duration = 0.3;
    if(CGSizeEqualToSize(cell.frame.size, self.itemSize)) { //shrinking cell
        animation.fromValue = @1.333;
        animation.toValue = @1;
    } else {                                                //expending cell
        animation.fromValue = @0.75;
        animation.toValue = @1;
    }
    [cell.layer addAnimation:animation forKey:@"transform.scale"];
}
0

Source: https://habr.com/ru/post/1626918/


All Articles