wj313
wj313

Reputation: 85

Resize / scale content of UICollectionView cell within layout transition

I'm playing around with the transition of the CollectionViewLayout of the examples projects from https://github.com/hebertialmeida/HAPaperViewController and https://github.com/wtmoose/TLLayoutTransitioning and couldn't figure out how to autoresize the content of the cell between the small and large layout.

E.g. I have an UILabel within the CollectionViewCell which should be half the width of the cell at a defined (fixed) position. When the transition to the large layout is finished, the label should be also half of the cell (same relative position), but with a larger font size (or resized).

Use autolayout here or scale the contentView with CGAffineTransformMakeScale?

Upvotes: 3

Views: 4887

Answers (1)

Timothy Moose
Timothy Moose

Reputation: 9915

I've updated the "Resize" sample project in TLLayoutTransitioning to demonstrate how this can be done.

The approach involves updating the font size at every step of the transition using one of the TLLayoutTransitioning callbacks. You probably don't want to use an affine transform because you'll get blurry scaled text at the large size.

The first step is to define a method to set the label's font size. You can use any formula you like, but I've make the font scale proportionally to the cell's width:

- (void)updateLabelScale:(UILabel *)label cellSize:(CGSize)cellSize
{
    CGFloat pointSize = cellSize.width * 17 / 128.f;
    label.font = [UIFont fontWithName:label.font.fontName size:pointSize];
}

You'll want to call this method in cellForItemAtIndexPath to ensure that new labels appearing on screen are properly scaled:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [super collectionView:collectionView cellForItemAtIndexPath:indexPath];
    UILabel *label = (UILabel *)[cell viewWithTag:1];
    ...
    [self updateLabelScale:label cellSize:cell.bounds.size];
    return cell;
}

The label's center is constrained to the center of the cell and the size is determined by the intrinsicContentSize. So, when you change the font, the label's size will automatically adjust to fit.

Finally, you'll use the updateLayoutAttributes callback to update the font size of visible cells based on the new layout attributes (you don't need to worry about cells that aren't visible because you're taking care of that in cellForRowAtIndexPath):

__weak ResizeCollectionViewController *weakSelf = self;
[layout setUpdateLayoutAttributes:^UICollectionViewLayoutAttributes *(UICollectionViewLayoutAttributes *pose, UICollectionViewLayoutAttributes *fromPose, UICollectionViewLayoutAttributes *toPose, CGFloat progress) {
    CGSize cellSize = pose.bounds.size;
    UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:pose.indexPath];
    if (cell) {
        UILabel *label = (UILabel *)[cell viewWithTag:1];
        [weakSelf updateLabelScale:label cellSize:cellSize];
    }
    return nil;
}];

Upvotes: 3

Related Questions