Search code examples
iosswiftuicollectionviewautolayout

Height of UICollectionViewCell with 2 multiline UILabels / self sizing collection view cells


I have a UICollectionViewCell prototype which should look like this:

enter image description here

On the left side, there is a UIImageView which I centered vertically in and pinned it to the start of the UICollectionViewCell.

Next comes a title UILabel which I pinned to the top and end of the UICollectionViewCell. I also pinned it to the end of the UIImageView.

Below comes a detail UILabel which I pinned to the bottom of the title, the end of the UICollectionViewCell and constraint it to have the same width as the title.

Below that comes a description UILabel which I pinned to the bottom of the detail, the end of the UICollectionViewCell and the bottom of the UICollectionViewCell. It also has the same width as the title.

What I want to achieve

The title and description labels have 0 number of lines (multiline) because I don't know how many lines the labels will have at runtime.

Via my custom UICollectionViewLayout I provide the target width for the cell. Now I need to figure out, how height the cell must be for the given width.

I have a non visible UICollectionViewCell which I think I can use to calculate the sizes by setting the model from my datasource. But I have a problem.

The Problem

After I set the text of the labels in my "size calculation cell", what do I do with the width and what else do I have to do so I can let the auto layout system calculate a proper height for the cell which I can then return to my UICollectionViewLayout

Or in other words: how can I tell the cell to use the new width to calculate its height.


Solution

  • Okay it seems that I misunderstood how to use sizeThatFits. I now went with a different approach, though. This is what I did to get my self-sizing cells:

    • I put the three labels in a vertical UIStackView
    • I put the UIImageView and the UIStackView in a horizontal UIStackView
    • I pinned to parent stack view to left, right, top and bottom of the cell where the bottom constraint is >= 0 instead of just = 0
    • I use a protocol in my UICollectionViewLayout to ask for the height of a given width
    • In my UICollectionViewController, I implement the protocol and where I register my cells, I also instantiate one of the cells which I use for measuring in the protocol function
    • In the protocol, I first get the model object, then I hand down the model to my measuring cell which I keep in an instance variable in my view controller
    • I then call getHeight(forWidth) on my cell. In this function, I set the cells frame.size.height to a very large number. Then I use AutoLayout to calculate the actual height (setNeedsDisplay(), layoutIfNeeded())
    • The height I need is the height of the parent stack view plus the margings

    I hope this helps somebody like me in the future. I also wrote a small blog post with some code samples of what I'm doing.