ios – UICollectionView inside UITableviewCell give wrong contentSizeHeight at first time but becomes true after scroll

[ad_1]

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

[ad_2]

Source link

Leave a Reply

Your email address will not be published.