4

My question is related to this one: How to change height Constraint of UIView in UitableviewCell when using UITableViewAutomaticDimension

The solution there does not seem to be working for me.

enter image description here

In the image above i have a simple cell. On tap of cell, i want to change the constraint of the redView to be larger. This should then automatically change the height of the cell.

I already have the height constraint of the cell set to an @IBOutlet and i think i am correctly changing the size of the cell, but it is not working.

Here is my sample app that is not working. Any help? SampleApp - for Xcode 9.3

Just a coder
  • 15,480
  • 16
  • 85
  • 138

2 Answers2

6

You need to set a bottom constraint to the red view so auto-layout can stretch the cell after setting the constant value

extension ViewController: UITableViewDataSource, UITableViewDelegate {

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "c", for: indexPath) as! customcell
        configure(cell: cell, indexPath: indexPath)
        cell.redview.backgroundColor = .red
        cell.selectionStyle = .none
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath) as! customcell
        cell.constraint.constant = data[indexPath.row] == "contracted"  ? 30 : 200
        data[indexPath.row] = data[indexPath.row] == "contracted" ? "expanded" : "contracted"
        tableView.reloadData()
    }

    func configure(cell: customcell, indexPath: IndexPath) {
        let data = self.data[indexPath.row]
        if data == "expanded" {
            cell.constraint.constant = 200
        } else {
            cell.constraint.constant = 30
        }

        cell.layoutIfNeeded()
    }
}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • 1
    you have to do that , he gives a conflict because he suggests a pre-height before auto-layout establishes the correct height according to the content you can set the priority of the this bottom constraint to 999 to prevent the conflicts log – Shehata Gamal Jul 14 '18 at 12:25
  • in else you set it to 30 tried to make it say 300 and check ?? – Shehata Gamal Jul 14 '18 at 12:53
  • Have you tried this in the sample zip file i provided above? It does not work :( Here is my updated project according to what you have said -> https://github.com/patchthecode/JTAppleCalendar/files/2194962/test.zip – Just a coder Jul 14 '18 at 13:44
  • Yes , tried and it works , you set the data to Contacted in the array so the else runs where you set the constraint's constant to 30 , you may be mistakenly think that if will run with constant 200 – Shehata Gamal Jul 14 '18 at 13:51
  • I think there is a misunderstanding. When you tap on the cell, it is supposed to expand to 200, when you tap on the cell again, it is supposed to contract to 30. When you tap again it is supposed to expand again (etc etc). The the size of the cell expand and contract like this when you try it? – Just a coder Jul 14 '18 at 14:03
  • Seeing `cell.layoutIfNeeded()` seems very strange. Better to trigger relayout correctly, e.g. `beginUpdates(); endUpdates();` and update only the necessary cells. You can actually just set the content on the changed cells without a reload. – Sulthan Jul 14 '18 at 16:21
  • @Sulthan always i prefer **cell.layoutIfNeeded()** to force correct layout as it glitches&flickers in complex cell-layout , putting content only yes we can access the cell and change it , but changing the layout of a cell affects other ones that's why it's a whole reload not reloading that specific index any way it will occur with visible cells only – Shehata Gamal Jul 14 '18 at 16:33
  • 1
    @Sh_Khan If only sizes change, then `beginUpdates & endUpdates` combo is superior to your solution. Reloading the whole table often has other serious implications. `layoutIfNeeded` should not be needed anyway. – Sulthan Jul 14 '18 at 16:37
  • Putting **layoutIfNeeded** in **cellForRowAt** dates back to IOS 8 automatic tableViewCells bug , since i support them in apps it's not removed till now – Shehata Gamal Jul 14 '18 at 16:45
  • cell.layoutIfNeeded() this line saves my time. Thanks – Muhammad Danish Qureshi Aug 09 '23 at 08:01
5

Calling the below will recalculate the heights.

[tableView beginUpdates];
[tableView endUpdates];
particleman
  • 635
  • 1
  • 7
  • 12
  • It depends on how you trigger the height change. If it's done in-cell, you'll probably need a delegate callback to your table view controller since the cell doesn't have a tableView reference. Like https://stackoverflow.com/questions/1110482/reference-from-uitableviewcell-to-parent-uitableview. – particleman Jul 14 '18 at 17:18