Bummer! You must be logged in to access this page.

Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

CollectionViewCell with dynamicFont using auto layout for cell height calculation

I'm building a collection view to replace an existing table view. In my table view I already support dynamic font sizing by using auto-layout and specifying that my table view's cell height is: UITableViewAutomaticDimension.

Question is, after I've created my layout for a collection view cell, and I know the width will be fixed as the width of the collection view's bounds, how can I specify the appropriate dynamic height for the collection view cell (keeping in mind this height changes as my font size is changed from native settings)?

I know that there are very long convoluted ways to calculate this - but I was wondering if there is something easier since auto-layout should theoretically always know the preferred height for my collection view cell.

2 Answers

Just in case anyone else is looking for the solution to this; the best way to approach this seems to be to create an instance of your custom cell class as an instance variable called "sizingCell" and then run a specific layout method on that cell after configuring it and forcing it to layout it's subviews. See code below:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    [self configureCell:_sizingCell atIndexPath:indexPath];

    [_sizingCell setNeedsUpdateConstraints];
    [_sizingCell updateConstraintsIfNeeded];
    [_sizingCell setNeedsLayout];
    [_sizingCell layoutIfNeeded];


    CGSize cellSize = CGSizeMake(self.collectionView.bounds.size.width, [_sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height);

    return cellSize;
}

Also, if you use multi-line labels you will need to set the following in an overridden layoutSubviews method in the custom cell class:

- (void)layoutSubviews {

    //NSLog(@"Printing heading label bounds width: %f", _headingLabel.bounds.size.width);

    _headingLabel.preferredMaxLayoutWidth = _headingLabel.bounds.size.width;
    _subheadingLabel.preferredMaxLayoutWidth = _subheadingLabel.bounds.size.width;

    [super layoutSubviews];
}

according to this stack overflow post

If you want to implement iOS dynamic heights using UICollectionViewCells with UITextViews you are going to need to implement -[UICollectionViewCell preferredLayoutAttributesFittingAttributes:] in addition to the estimatedItemSize property on the flow layout (assuming you are using flow layout).

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    UICollectionViewLayoutAttributes *attr = [layoutAttributes copy];
    CGSize size = [self.textView sizeThatFits:CGSizeMake(CGRectGetWidth(layoutAttributes.frame),CGFLOAT_MAX)];
    CGRect newFrame = attr.frame;
    newFrame.size.height = size.height;
    attr.frame = newFrame;
    return attr;
}
UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *) self.collectionView.collectionViewLayout;
flowLayout.estimatedItemSize = CGSizeMake(yourestimatedWidth, yourestimatedHeight)];

Thanks for the response. Unfortunately I am not using a TextView and I have a variety of different controls inside of the CollectionViewCell including UIImageView, multiple labels etc.

I was hoping their might be some alternative solution.