UICollectionView Self Sizing Cells with Auto Layout

前端 未结 16 2012
野性不改
野性不改 2020-11-22 05:58

I\'m trying to get self sizing UICollectionViewCells working with Auto Layout, but I can\'t seem to get the cells to size themselves to the content. I\'m having

16条回答
  •  爱一瞬间的悲伤
    2020-11-22 06:11

    The solution comprises 3 simple steps:

    1. Enabling dynamic cell sizing

    flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

    1. Set the containerView.widthAnchor.constraint from collectionView(:cellForItemAt:)to limit the width of contentView to width of collectionView.
    class ViewController: UIViewController, UICollectionViewDataSource {
        ...
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! MultiLineCell
            cell.textView.text = dummyTextMessages[indexPath.row]
            cell.maxWidth = collectionView.frame.width
            return cell
        }
    
        ...
    }
    
    
    class MultiLineCell: UICollectionViewCell{
        ....
    
        var maxWidth: CGFloat? {
            didSet {
                guard let maxWidth = maxWidth else {
                    return
                }
                containerViewWidthAnchor.constant = maxWidth
                containerViewWidthAnchor.isActive = true
            }
        }
    
        ....
    }
    

    Since you want to enable self-sizing of UITextView, it has an additional step to;

    3. Calculate and set the heightAnchor.constant of UITextView.

    So, whenever the width of contentView is set we'll adjust height of UITextView along in didSet of maxWidth.

    Inside UICollectionViewCell:

    var maxWidth: CGFloat? {
        didSet {
            guard let maxWidth = maxWidth else {
                return
            }
            containerViewWidthAnchor.constant = maxWidth
            containerViewWidthAnchor.isActive = true
            
            let sizeToFitIn = CGSize(width: maxWidth, height: CGFloat(MAXFLOAT))
            let newSize = self.textView.sizeThatFits(sizeToFitIn)
            self.textViewHeightContraint.constant = newSize.height
        }
    }
    

    These steps will get you the desired result.

    Complete runnable gist

    Reference: Vadim Bulavin blog post - Collection View Cells Self-Sizing: Step by Step Tutorial

    Screenshot:

提交回复
热议问题