Swift2Go
Published in

Swift2Go

Implementing a Dynamic Height UICollectionViewCell in Swift 5

Creating a UICollectionViewCell to have a dynamic height based on font size and image aspect ratio

Photo by Tim Bennett from Unsplash

The Problem

Sometimes we need to be UICollectionView’s Cells have size depend on their content and the most common example is the feeds in social websites every post has a different size as well as their comments.

I’ve searched for a solution many of them didn’t work on iOS 14 & Swift 5 and some depend on third-party libraries so I decided to write this article.

This tutorial has two parts. First, We’re going to implement a self-sizing UICollectionViewCell based on font size as shown in the screenshot on the left side.

Second we’re going to build a dynamic height UICollectionViewCell based on the image aspect ratio in addition to font size the result will be like the right side of the screenshot.

Dynamic Height UICollectionViewCell

Part1: Self-Sizing UICollectionViewCell based on font size only

It consists of three steps the first is creating and configuring the cell then we’re going to subclass UICollectionViewFlowLayoutafter that, we would configure UICollectionView.

Step 1: Create and Configure UICollectionView Cell

We’re going to create a simple cell to display a photo as well as the name of the user and his comment.

Please notice that I’ve used an extension to set up Auto layout Constrains you can check out this link

Now we should modify the cell’s frame in order to set a dynamic size based on the font size to do so we have to override preferredLayoutAttributesFitting method so copy the snippet below to our custom cell.

layoutAttributes are the values which would be applied on the cell

Step 2: Subclass UICollectionViewFlowLayout

Step 3: Configure UICollectionView

In the last step, we have to set up our UICollectionViewwith an instance of CommentFlowLayoutclass to do so just paste the code below at viewDidLoad method.

Part2: UICollectionViewCell Height based on the image aspect ratio and font size

We‘re going to display two columns in the row so we have to calculate the cell’s positions manually in our subclassed UICollectionViewFlowLayout because we have different heights.

To do so we’ll adapt a nice solution was introduced by the raywenderlich team they implement a dynamic cell based on photo height you can check out the article here, however, we want to size the UICollectionViewCell based on the aspect ratio of the photo and the font.

Step 1: Create and Configure UICollectionView Cell

We’re going to create the feed cell to display a photo and dummy description text below it.

Notes:

  1. We’ve set up setContentHuggingPriority for the label to high value because we need to have size only to display the content, unlike the UIImageView we assigned to a low value to get the remaining space
  2. We assigned zero to numberOfLines of the label in order to display multiline and we initialized the lineBreakMode property with byWordWrapping value.

We should add constraints to our cell so add this function to FeedCell and then call it after setupViews function

Notice that first, we pinned the photo to the four edges of the contentView after that, we linked the description lable with the bottom of the photo with a 5 margin.

Step 2: Subclass UICollectionViewFlowLayout

Create a class called it PinterestLayout then paste the code below

Notes:

  1. We’ve introduced a delegate to communicate with our ViewController in order to get the cell’s height
  2. In prepare function, we calculated the cell’s size and their position then we cashed them instead of recalculating the attributes every time.

Step 3: Configure UICollectionView

We have to create and an instance of our PinterestLayout class then assign it as a layout to the UICollectionView.

The Tricky part

We need to confirm our protocol PinterestLayoutDelegate that we had created earlier which ask our ViewController about the height of the cell but how will we calculate it?

We‘re going to write two functions one to calculate the appropriate photo’s height and another to calculate the required space to display the description so let’s start with the first one.

Here we need our API to provide so important information to help us figure out the perfect size based on the image aspect ratio to do so the backend developer must supply the dimensions of the photo as shown below

So we figured out the new height based on the old dimension in addition to the cell width.

Now let’s move to the second function calculating text’s space needed we’ll create a fake Lable then place our text after that the function will return the Lable’s height

Notes:

  1. You have to use the same font attributes as well as the lineBreakMode value that was set up in the first step when we created the custom cell
  2. You must call sizeToFit function

Merge the pieces together

Now we are ready to satisfy Xcode and make it stop complaining about PinterestLayoutDelegate protocol.

Notes:

  1. We’ve added 5 value into the total because earlier at design the custom cell we had left margin between the photo and the label.
  2. Headers are a dummy string array was generated using Fakery

The Conclusion

We’ve implemented two approaches to create UICollectionViewCell with dynamic height programmatically based on its content which is compatible with Swift 5 without any third-party, First one was based on the font size, while the second was based on photos’ size that was fed via API in addition to the description text‘s size.

I published the source code on GitHub.

Further reading :

Extending UICollectionView with a Centered UIActivityIndicatorView

Adding a loading indicator to your infinite UICollectionView

Creating a native popup menu over a UIButton or UINavigationBar

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store