Search code examples
iosswiftautolayoutcollectionview

CollectionView AutoResize Label Not Working


I have a vertical collectionview with label and in my flowlayout i am using UICollectionViewFlowLayoutAutomaticSize to resize the cell size but it is giving me error when i give very long string to the label, number of line in label set to 0

Error

Please check the values returned by the delegate. The relevant

UICollectionViewFlowLayout instance is UICollectionViewFlowLayout ,and it is attached to UICollectionView; frame = (0 88; 375 690); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = NSArray layer = CALayer; contentOffset: {0, 0}; contentSize: {375, 2}; adjustedContentInset: {0, 0, 0, 0}> collection view layout: UICollectionViewFlowLayout

Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.

The behavior of the UICollectionViewFlowLayout is not defined because the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values

Constraints

enter image description here

Code

let array = ["Hello", Array(repeating: "Hello", count: 100).joined(), "blah"]
// on viewDidLoad method
 if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
        flowLayout.estimatedItemSize = CGSize(width: 1, height: 1)
        flowLayout.itemSize = UICollectionViewFlowLayoutAutomaticSize
    }

Solution

  • Problem is that for some reason UICollectionViewFlowLayout does not set maximum width of the the cell, and since you have constraints set like you do, what happens is that width of a cell or multiple cells is bigger than width of the collectionView.

    Here is how to fix it, add a width constraint to your label inside of your UICollectionViewCell subclass and set it not to equal but to less than equal.

    Add a constraint

    Next make an outlet to that constraint so that it will be possible to be set later.

    Outlet

    Then in CollectionViewDataSource cellForItemAtIndexPath you can set the width constant to be smaller than CollectionView width minus padding you added (in my case label has padding 20 + 20 for left and right).

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "reuse", for: indexPath) as! CollectionViewCell
    
        cell.widthConstraint.constant = collectionView.bounds.size.width - 40
        //line above sets maximum width of label to be maximum the width of the collection view
        cell.label.text = array[indexPath.item]
        return cell
    }
    

    The result is collection view like below:

    enter image description here