Reputation: 51
I have a collection view which makes use of a custom layout. I'm trying to calculate the height dynamically, but the problem is sizeForItemAt:indexPath is called before cellForItemAt:indexPath.
My cells get loaded in cellForItemAt. But since sizeForItemAt is called before cellForItemAt, then I can't use my calculated height.
I know with Apple's FlowLayout I can just set the estimatedItemSize for the layout. I'm not sure how to do it with a custom layout.
Please advise. Thank you!
Upvotes: 0
Views: 760
Reputation: 1178
I had the same problem, my app uses custom layout with dynamic height. I found that with custom layout that doesn't extend UICollectionViewFlowLayout
or any other default layout, dynamic height will not work because as per Apple documentation (and like you probably noticed) with a completely custom layout you have to predefine all the cells X, Y, width, height before the cell load and before you even have data.
I changed my custom layout to subclass UICollectionViewFlowLayout
and implemented UICollectionViewDelegateFlowLayout
. When this method is called the cell did not load yet but the cell's data is available since I know what the cell should look like (assuming you are using cell prototypes) I could calculate the cell width and height using its data and index, something like this:
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
// get the cell's data
if let data = self.fetchedResultsController.fetchedObjects![indexPath.row] as? YourDataType {
// carculate the cell width according to cell position
let cellWidth = carculateCellWidth(indexPath.row)
var cellHeight : CGFloat = 0
// assuming the cell have a label, set the label to have the same attributes as set in the storyboard or set programmatically
let label = UILabel()
label.numberOfLines = 0
label.font = UIFont.preferredFont(forTextStyle: .subheadline)
label.text = data.text
// carculate the height of the cell, assuming here the label width equal the cell width minus 10px left and right padding.
cellHeight += label.systemLayoutSizeFitting(CGSize(width:cellWidth-20, height: CGFloat(Float.greatestFiniteMagnitude))).height
return CGSize(width: cellWidth, height: cellHeight)
}
return .zero
}
This is not a very elegant solution but it works.
Upvotes: 1