UICollectionViewCell dynamic height w/two dynamic labels & auto layout
Asked Answered
S

1

5

I have a UICollectionViewCell subclass that's setup with a prototype cell and constraints (every view is connected both vertically and horizontally).

I have two labels that can vary in size, they can be either one or two lines. To that end I have set two height constraints on each label, one with a greater than or equal (16 or 20 depending on the label) and a less than or equal (32 or 40 depending on the label).

The number of lines on the labels are set to 0. (Though I have tried a variety of settings).

Since I've used auto layout and constraints to setup the view I've specified a width on the content view in the cell's awakeFromNib()

override func awakeFromNib() {
        NSLayoutConstraint.activate([contentView.widthAnchor.constraint(equalToConstant: 341)])
        super.awakeFromNib()
        configureBorder()
}

On the collectionView's layout I've specified the automaticDimension constant for estimateItemSize & itemSize

if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
    flowLayout.itemSize = UICollectionViewFlowLayoutAutomaticSize
}

With the idea of using auto layout I have not implemented a delegate on the collection view.

I am experiencing very inconsistent layout, some instances the cell's will appear as I'd like them to, in others the labels are truncated and in others the labels are extremely narrow and display text over three lines.

I have tried many things, including calling .sizeToFit() on each label after it's text property is set, as well as calling .setNeedsDisplay() before the cell returns from cellForItemAt

I'm wondering what is the right way to do this with storyboard constraints. I've worked with some of the popular answers to similar questions here on SO, though none to any real success.

Strage answered 30/7, 2018 at 1:12 Comment(0)
K
16
flowLayout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
flowLayout.itemSize = UICollectionViewFlowLayoutAutomaticSize

Of course I am familiar with Apple's repeated claims that a UICollectionViewCell in a UICollectionViewFlowLayout can be self-sizing based on internal constraints. But I have never seen working code from Apple that demonstrated this feature, and I have never once myself succeeded in confirming those claims to be true. I do not believe there is really such a thing as a self-sizing cell. For years, trying to get a cell to be self-sizing resulted in crashes. In iOS 10, the crashing mostly stopped, but now the flow layout was not laying out the cells correctly (which sounds like what you're seeing).

Naturally, I have filed bugs on all this, year after year.

Meanwhile, what I do is to give the collection view a delegate and implement collectionView(_:layout:sizeForItemAt:), and I suggest that you should do the same.


EDIT New in iOS 13 you can use a composable layout and abandon UICollectionViewFlowLayout altogether. Self-sizing cells work fine in a composable layout.

Kilt answered 30/7, 2018 at 1:19 Comment(6)
Thank you for the solid advice and sanity check.Strage
Just to expand a little, what I do in collectionView(_:layout:sizeForItemAt:) is what I would have expected the runtime to do: I apply systemLayoutSizeFitting(_:) to the cell's contentView to get the size dictated internally by the constraints of its subviews.Kilt
Now, having said all that, if you still can't get the cells to size correctly, then maybe something is wrong with your constraints. But at least we can take the automatic self-sizing out of the picture and focus on those, in another question.Kilt
I really tried my best as well to avoid using the sizeForItemAt, but there's really no other solid choice unfortunately. The automatic size may work in some cases, but still, even when using a simple performBatchUpdates for instance, there are lots of glitches. For the systemLayoutSizeFittings I'm storing static copies of cells that I can configure thanks the view model. Couldn't find a smarter way to use the runtime cell that is crash-free. Do you adopt a cleaner way for it? TnxCareycarfare
@AlessandroFrancucci Not really. :) Once again Apple has claimed at WWDC 2019 that this time self-sizing collection view cells really really work this year (in iOS 13). But I have not tested yet.Kilt
Interesting, we'll see then! Thanks for the info :+1:Careycarfare

© 2022 - 2024 — McMap. All rights reserved.