I have a view that structured like this
-Tableview
- TableviewCell
- UICollectionView
- UICollectionViewCell
the uicollectionview cell defines a left align tag with collectionViewFlowLayout like this
class Row {
var attributes = [UICollectionViewLayoutAttributes]()
var spacing: CGFloat = 0
init(spacing: CGFloat) {
self.spacing = spacing
}
func add(attribute: UICollectionViewLayoutAttributes) {
attributes.append(attribute)
}
func tagLayout(collectionViewWidth: CGFloat) {
let padding = 0
var offset = padding
for attribute in attributes {
attribute.frame.origin.x = CGFloat(offset)
offset += Int(attribute.frame.width + spacing)
}
}
}
class LeftAlignTagCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else {
return nil
}
var rows = [Row]()
var currentRowY: CGFloat = -1
for attribute in attributes {
if currentRowY != attribute.frame.origin.y {
currentRowY = attribute.frame.origin.y
rows.append(Row(spacing: 4))
}
rows.last?.add(attribute: attribute)
}
rows.forEach {
$0.tagLayout(collectionViewWidth: collectionView?.frame.width ?? 0)
}
return rows.flatMap { $0.attributes }
}
}
this is code at datasource cellForRow in ViewController that handle tableview
let cell = tableView.dequeueReusableCell(withIdentifier: "CollectionTableViewCell") as? CollectionTableViewCell
cell?.setupCell(showFirstItem: true, showSecondItem: true)
cell?.collectionView.reloadData()
cell?.layoutIfNeeded()
let height = cell?.collectionView.collectionViewLayout.collectionViewContentSize.height
cell?.collectionViewHeightConstraint.constant = height ?? 0
i have already call layoutIfNeeded() before accessing collectionview content size height and assign the contentsize height into collectionview height constraint. i already set isScrollEnabled to false.
and in the CollectionTableViewCell it looks like this
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint! // Required priority (1000)
private var collectionItem: [String] = []
override func awakeFromNib() {
super.awakeFromNib()
setupCollectionView()
collectionView.dataSource = self
collectionView.delegate = self
let layout = LeftAlignTagCollectionViewFlowLayout()
layout.estimatedItemSize = CGSize(width: 140, height: 40)
collectionView.collectionViewLayout = layout
}
func setupCell(showFirstItem: Bool, showSecondItem: Bool) {
setupCollectionItem()
}
private func setupCollectionItem(showFirstItem: Bool, showSecondItem: Bool) {
collectionItem = []
if showFirstItem {
let data = "TagNumber1"
collectionItem.append(data)
}
if showSecondItem {
let data = "TagNumber2"
collectionItem.append(data)
}
}
extension CollectionTableViewCell: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
private func setupCollectionView() {
collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CollectionViewCell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return collectionItem.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as? CollectionViewCell
cell?.configCell(model: collectionItem[indexPath.row], maxWidth: collectionView.frame.width - 8)
cell?.setNeedsLayout()
cell?.layoutIfNeeded()
return cell ?? UICollectionViewCell()
}
}
in summary, when i run the code above, it will give wrong content size height at first load lets say around 86.0 but after scrolling or reload tableview for the second time (i have two times reload tableview since there are two method for calling API in this ViewController) it gives correct number lets say the target that i want is 24.0 so when changing from first value 86.0 to 24.0 it gives a glitch in uitableviewcell. and i cannot hide the tableview until finish the process of collectionview height calculation. Another point is, if i have only one item at collectionItem it gives correct contentsize height! but when it turns into two items the problem showed.
waiting for your suggestion, Thank you