Sizing a UICollectionViewCell to Fit a Multiline UILabel

Written by: on February 5, 2016

UILabels and UICollectionViews are very common UI elements in iOS apps, and combining these can pose some interesting sizing problems. In this article, you will learn two methods for placing a multiline label inside a collection view cell.

A UILabel with its numberOfLines property set to 0 will expand its height to fit the text that you set. This resizing of the label’s frame will affect other views that depend on the label’s height, such as top and bottom constraints on a superview.

Placing this type of UILabel inside a UICollectionViewCell will cause a sizing problem as follows:

  • The cell needs to know its size to be displayed.
  • The cell height is determined by the label height (top and bottom constraints).
  • The label height is determined by the label width (or preferredMaxLayoutWidth).
  • The label width is constrained by the cell’s width.

In this situation, the height of a cell is determined by the width of the cell, which means you cannot specify both values at the same time, as required in sizeForItemAtIndexPath. In iOS 9, you can simply use auto layout and this problem will not be much of an issue.

Unfortunately, prior to iOS 9 you need to calculate the size of the cell, but you can leverage the power of the auto layout engine to make this easier. This technique can also be used for more complex layouts or if you just want to programmatically control the sizing.

This article assumes you are familiar with the basics of UIViewController, UICollectionView, and auto layout.

 

Method 1: Simple Auto Layout (iOS 9) Create a UICollectionView with a UILabel constrained to the top, left, bottom, and right edges of the cell.

Screen Shot 2016-01-26 at 12.58.08 PM[5]

 

 

First, you need to enable the collection view to use auto layout to size the cells. To do this, set the estimatedItemSize property of the collection view flow layout in viewDidLoad. This will cause the collection view to query each cell for its size, allowing auto layout to do its job.

if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { flowLayout.estimatedItemSize = CGSizeMake(1, 1) }

If you set estimatedItemSize too large, then you might get some weird scrolling behavior, so I recommend keeping the size small.

Second, you need to specify the width of the each label so that they will have a determinate size. This is easily accomplished by setting preferredMaxLayoutWidth to a positive value.

cell.label.preferredMaxLayoutWidth = 50

You can also assign a specific width to the label if you don’t want the cell to shrink for shorter text, but you still need to set preferredMaxLayoutWidth for the label to resize its height.

That’s it! Check out the sample project on GitHub and take a look at SimpleViewController for an example implementation of this method.

Method 2: Calculate Cell Size (iOS 8 & 9)Insights 2

Unfortunately, the above method does not work well for iOS versions prior to 9.0 and can give you some strange results plus take a toll on performance. 

For this method, you are going to use the sizeForItemAtIndexPath call from UICollectionViewDelegateFlowLayout to specify the size of each cell.

First, create a temporary cell that can be used for sizing purposes. One way to do this is to load a Nib file and grab the cell from the views (see the fromNib() method of LabelCollectionViewCell in the sample project). This cell will not be added to any view, it is only used for calculating the size.

Second, set the label’s preferredMaxLayoutWidth as in Method 1.

Third, return the size of the cell in sizeForItemAtIndexPath by calling systemLayoutSizeFittingSize.

cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

This will invoke the auto layout engine to return a size that satisfies the constraints for the cell. For more information on this method, see Apple’s documentation.

Check out CalculateViewController in the sample project for an example of Method 2. Instead of the cells shrinking their width to fit the text as in Method 1, this example maintains a constant number of columns no matter the size of the collection view (e.g. when the device is rotated).

Resources: 

Sample Project on Github

Getting Started with Collection Views on RayWenderlich.com

Getting Started with Auto Layout on RayWenderlich.com

Apple’s Documentation for:

UIView: systemLayoutSizeFittingSize

Jeremiah Gage

Jeremiah Gage

Jeremiah is a software engineer who specializes in iOS development. He moved to Denver, Colorado in 2014 to work for POSSIBLE Mobile. Jeremiah is also an avid billiards (pool) player and instructor.
Article


Add your voice to the discussion: