Cory Imdieke
Cory Imdieke

Reputation: 14828

UICollectionView Dynamic Sized Cells in only one direction

Is there a way to dynamically size UICollectionViewCells in only one direction, like height, while making the width follow the layout's itemSize dimension? Or is it all or nothing?

Upvotes: 0

Views: 743

Answers (2)

David Silverfarmer
David Silverfarmer

Reputation: 455

From iOS 8 on their is an api provided by Apple called Self-Sizing Cells, which is great and very easy to use (it does have some issues, but thoes are rather small compared to the benefits).

To use it you have to do two things:

  1. Set up auto layout in your cell so that a height and width can be obtained from the constraints.

  2. Simply set the estimatedItemSize property of the collection views layout object to a non-zero value:

    UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
    collectionViewLayout.estimatedItemSize = //your estimated item size
    

That's it for self-sizing cells (for more info watch the WWDC 2014 video "What's New in Table and Collection Views")! If you want more fine grained control you will probably need to subclass UICollectionViewLayout...

Upvotes: 1

Aleš Kocur
Aleš Kocur

Reputation: 1908

You can create a cell for sizing purposes from NIB for example:

_sizingCell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([MyCell class]) owner:self options:nil] firstObject];

Let's assume that MyCell has a titleLabel for exmpl. Then you can let the autolayout calculate the size for you in collectionView:layout: sizeForItemAtIndexPath:

NSString *title = self.items[indexPath.item];
self.sizingCell.titleLabel.text = item.title;

CGSize size = [self.sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

return CGSizeMake(size.width, 33);

This operation can take a time, so I suggest to cache the calculated value. Let's create property NSCache *cellWidthCache

NSString *title = self.items[indexPath.item];
self.sizingCell.titleLabel.text = item.title;

NSNumber *cachedWidth = [self.cellWidthCache objectForKey:indexPath];

if (!cachedWidth) {
    cachedWidth = @([self.sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].width);
    [self.cellWidthCache setObject:cachedWidth forKey:indexPath];
}

return CGSizeMake(cachedWidth.floatValue, 33);

Upvotes: 2

Related Questions