Ios – UITableViewCell with StackView not dynamically sizing height

iosswiftuikituitableview

I have a custom UITableViewCell that contains a StackView with top, bottom, leading and trailing constraints to the content view of the cell.

When I set up my tableView, I give it an estimated height and also set the rowHeight to UITableViewAutomaticDimension.

In my cellForRowAt datasource method, I dequeue the cell and then call cell.setup() which adds any given number of views to my cell's stackView.

The problem is: My cell is always being sized to the estimated height of 80p. No matter how many views I add to the cell's stackView, it all crams into 80p height. The stackView, and thus the cell, isn't growing with each new item I insert into the cell before returning it in cellForRowAt datasource method.

I tried different distribution settings for my stackView, but I'm not sure what I'm doing wrong here.

Best Answer

Here is a simple demonstration of adding buttons to a stack view inside an auto-sizing table view cell:

class StackOfButtonsTableViewCell: UITableViewCell {

    @IBOutlet var theStackView: UIStackView!

    func setup(_ numButtons: Int) -> Void {

        // cells are reused, so remove any previously created buttons
        theStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }

        for i in 1...numButtons {
            let b = UIButton(type: .system)
            b.setTitle("Button \(i)", for: .normal)
            b.backgroundColor = .blue
            b.setTitleColor(.white, for: .normal)
            theStackView.addArrangedSubview(b)
        }

    }

}


class ViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 100
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 6
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "StackOfButtonsTableViewCell", for: indexPath) as! StackOfButtonsTableViewCell

        cell.setup(indexPath.row + 1)

        return cell

    }

}

Assuming you have created a prototype cell, and its only content is a UIStackView configured as:

Axis: Vertical
Alignment: Fill
Distribution: Equal Spacing
Spacing: 8

and you have it constrained Top/Leading/Trailing/Bottom to the cell's content view, this is the result:

enter image description here

No need for any height calculations, and, since buttons do have intrinsic size, no need to set height constraints on the buttons.

Related Topic