Search code examples
uicollectionviewuikituicollectionviewcell

Can't CollectionViewCell Dynamic Label Width in TableViewCell


I placed a CollectionView inside a TableViewCell. I added a Label inside the CollectionViewCell and set up all the constraints using Xib. However, the CollectionView still relies on the width and height values in the Show Size Inspector section. I have set the Estimate Size value to Automatic in the Show Size Inspector tab, but the CollectionViewCell continues to be dependent on the Width and Height values within the Show Size Inspector. When I correctly set all the constraints, it should be dynamic. What am I doing wrong?

Simulator SS:

enter image description here

MainVC:

final class MainVC: UIViewController {

    @IBOutlet private weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        registerCells()
    }
    
    private func registerCells() {
        tableView.register(cellClass: CategoryListCell.self)
    }
}

extension MainVC: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeue(CategoryListCell.self, indexPath: indexPath) {
            return cell
        }
        return UITableViewCell()
    }
}

CategoryListCell(XIB):

enter image description here

CategoryListCell:

class CategoryListCell: UITableViewCell {

    @IBOutlet private var collectionView: UICollectionView!
    let categories: [String] = [
        "All",
        "Nature",
        "Horror",
        "Crovd",
        "Apartments",
        "Planets"
    ]
    
    override func awakeFromNib() {
        super.awakeFromNib()
        registerCell()
        let collectionFlowLayout = UICollectionViewFlowLayout()
        collectionFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
        collectionView.collectionViewLayout = collectionFlowLayout
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        
    }
    
    private func registerCell() {
        collectionView.register(cellClass: CategoryListItemCell.self)
    }
}

extension CategoryListCell: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return categories.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if let cell = collectionView.dequeue(CategoryListItemCell.self, indexPath: indexPath) {
            cell.prepareCell(with: categories[indexPath.row])
            return cell
        }
        return UICollectionViewCell()
    }
}

CategoryListItemCell(XIB):

enter image description here

CategoryListItemCell:

final class CategoryListItemCell: UICollectionViewCell {
    
    @IBOutlet private var categoryTitleLabel: UILabel!
    @IBOutlet private var bottomLineView: UIView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        bottomLineView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            bottomLineView.widthAnchor.constraint(equalTo: categoryTitleLabel.widthAnchor)
        ])
    }
    
    func prepareCell(with model: String) {
        categoryTitleLabel.text = model
    }
}

Solution

  • I replicated your XIBs, and the issue is that you have your Bottom Line View constrained to width = 4.

    Then, in your class awakeFromNib() you are setting the categoryTitleLabel width equal to the bottomLineView width -- so the label width is then also 4.

    Change the constraints in your XIB to this (I set the label background to yellow so we can see it):

    enter image description here

    Note: I also set the label's Vertical Content Hugging Priority to Required (1000).

    and your class becomes:

    final class CategoryListItemCell: UICollectionViewCell {
        
        @IBOutlet private var categoryTitleLabel: UILabel!
        @IBOutlet private var bottomLineView: UIView!
    
        func prepareCell(with model: String) {
            categoryTitleLabel.text = model
        }
    }
    

    The result -- view background is light-gray, table is white, collection view background is green:

    enter image description here