swiftuicollectionviewuicollectionviewcelluicollectionviewlayoutuicollectionviewdelegateflowlayout

CollectionViewLayout Height


I want to custom a lot of layout size for each row of my collectionView by using UICollectionViewDelegateFlowLayout like below:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = view.frame.width
        if indexPath.row == 0 {
            return CGSize(width: width, height: 300)
        }else if indexPath.row == 1 {
            return dynamicSize // i want this size wrap its content
        }
        return CGSize(width: width, height:100)
}

I want dynamicSize that can wrap its content for some row. Anyone know how to do this?

Here is image of cell that i want dynamic size to wrap it.

enter image description here


Solution

  • I suggest you to use tableview instead of collectionview. It is very easy for you.

    And for cellForHeight returns UITableViewAutomaticDimension. It will calculate your cell height itself and adjust it accordingly.

    Note: Make sure your constraints are proper.

    Edit: By using collectionview with two columns.

    class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
        var text = "Do any additional setup after loading the view, typically from a nib."
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
        }
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets{
            return UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
    
            let cellWidth = self.view.frame.size.width/2 - 10
            let textHeight = text.height(withConstrainedWidth: cellWidth, font: UIFont.systemFont(ofSize: 16))
            let constantHeight : CGFloat = 40 + 25 + 10 // top name view + bottom like button + margins height
            let totHeight = constantHeight + textHeight
    
            return CGSize(width: cellWidth, height: totHeight)
        }
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 10
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell  = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCollectionViewCell", for: indexPath) as! MyCollectionViewCell
    
            cell.label.text = text
            cell.layer.borderWidth = 1.0
            cell.layer.borderColor = UIColor.black.cgColor
            return cell
        }
    
    }
    
    extension String {
        func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
            let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
            let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)
    
            return ceil(boundingBox.height)
        }
    
        func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
            let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
            let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)
    
            return ceil(boundingBox.width)
        }
    }
    

    Output:

    enter image description here