tendai
tendai

Reputation: 1251

Loading different heights for cell with UICollectionView

I am trying to dynamically adjust cells in a CollectionView according to the contents of a label. Basically i have found how to but my challenge is

cellForItemAt method

gets called first before

heightForCellAtIndexPath method

and by doing so this means we are trying to get heights before data is loaded so the cells will always be the same height and therefore we wont achieve different heighted cells

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let content_ = content[indexPath.row]
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "NotesUI", for: indexPath) as! NotesUI
            cell.setData(data: content_)
            return cell
    }


 func collectionView(_ collectionView: UICollectionView, heightForCellAtIndexPath indexPath:IndexPath) -> CGFloat {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "NotesUI", for: indexPath) as! NotesUI
    return cell.allNoteViews()[indexPath.item - 1].bounds.size.height
  }

Essentially in the NotesUI CollectionView class:

class NotesUI:UICollectionViewCell{
    @IBOutlet var note: UILabel!
    var views: [UILabel] = []
    
    func setData(data: NoteModel){
       note.text = data.note
       note.numberOfLines = 0
       note.lineBreakMode = NSLineBreakMode.byWordWrapping
       note.sizeToFit()
     
       views.append(note)
    }
    
     func allNoteViews()->[UILabel]{
        return views
    }
}

I guess my question boils down to how can i call heightForCellAtIndexPath method after the cellForItemAt method so that the CollectionView gets the height of the label after it has contents

Upvotes: 1

Views: 208

Answers (1)

ibrahimyilmaz
ibrahimyilmaz

Reputation: 2335

You don't need to calculate each cell height if you use auto layout. You can add a vertical stack view to your cell and add your labels to it.

Here is a basic example of self-sizing collection view cells.

class YourCustomCell: UICollectionViewCell {
    
    // Add your labels to this stackView
    @IBOutlet weak var yourLabelContainer: UIStackView!
        
    override func awakeFromNib() {
        super.awakeFromNib()
        
        yourLabelContainer.translatesAutoresizingMaskIntoConstraints = false
        yourLabelContainer.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.size.width - 32).isActive = true // for 16 - 16 padding
    }
}


class YourViewController: UIViewController {

    @IBOutlet weak var yourCollectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        yourCollectionView.delegate = self
        yourCollectionView.dataSource = self
        
        let nib = UINib(nibName: "YourCustomCell", bundle: nil) 
        yourCollectionView.register(nib, forCellWithReuseIdentifier: "cellReuseId")
        
        if let layout = yourCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
        }
    }
}

Upvotes: 1

Related Questions