4

My iOS app has a tableview with one UITableViewCell with the following layout (1 stackview containing 2 labels and 1 button)

enter image description here

When the user taps the button the number of lines of the central label goes from 0 to 2 and will look like this:

enter image description here

Now there are two problems here:

1) Resizing the UIStackView

2) Resizing the cell

I have found a not-optimal solution for problem 1, which consists of adding an empty view in the stack. (invalidateIntrinsicContentSize was not working).

let emptyView = UIView()
emptyView.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
stackView.addArrangedSubview(emptyView)

As you can see in the second screenshot the cell doesn't resize and I'm not sure if this is due to the stackview or the cell itself.

I would like to point the fact that I'm writing code inside the UITableViewCell subclass as the button event is handled inside it.

For the records The Tableview is using dynamic sizing:

// dynamic cell sizing 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {

    return CGFloat(cellEstimatedHeight)
}
Claus
  • 5,662
  • 10
  • 77
  • 118
  • Are you triggering a reload for that tableView for that indexPath? – Ryan Poolos Mar 23 '17 at 19:07
  • from inside the cell I did: `let tableview = self.superview as? UITableview tableview.reloadData()` but it doesn't work – Claus Mar 23 '17 at 19:16
  • I guess it would be the same just for one row – Claus Mar 23 '17 at 19:16
  • Accessing the tableView as the superView is very fragile. And unlikely to work if the tableView has any subviews. I'd recommend giving your cell a delegate and from there reloading the tableView – Ryan Poolos Mar 23 '17 at 19:31
  • @Claus, You found the solution? I am also facing the same problem. I have UIWebView and UIImageView inside UIStackView. when Both views are available inside stackView, it works fine. But, when I hide UIImageView, UIwebView height becomes larger than UIStackView for larger data. – Mansuu.... Oct 10 '17 at 17:55

1 Answers1

1

UIStackView may or may not be your best bet... it's designed more for arranging views inside its own frame, rather than adjusting its own frame to the views.

For a layout as simple as you have there, it would probably be much better to just lay out the elements with normal constraints.

Take a look at this example: https://github.com/DonMag/DynamicCellHeight

Table B is one way of accomplishing your layout (Table A was for another layout I played around with).

I had to do a little trickery to get the main label to stay in place while the cell resized... could probably find a better way. (Re-Edit - yep, found a better way)

Let me know if it makes sense - no doubt you'll want to do some tweaking.

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • I would need a way to trigger the resize of the cell from inside UITableView Cell I have tried: `self.stackView.invalidateIntrinsicContentSize()` `self.setNeedsLayout()` `self.setNeedsDisplay()` but nothing – Claus Mar 23 '17 at 19:11
  • I could use a simpler layout, but to be honest I like the way UIStackView works and I would prefer to stick with this choice. – Claus Mar 23 '17 at 19:18
  • 2
    Amazing it works. So the trick is (once got a reference to the table) to do: `tableview?.beginUpdates() tableview?.endUpdates()` thanks a lot!!! – Claus Mar 24 '17 at 09:50
  • There are other uses for `tableview?.beginUpdates()` and `tableview?.endUpdates()`, but yep... they can be called back-to-back like that to force the table to re-calculate row heights without running through a `.reloadData()`. The real tricky part was using constraints on a *sorta hidden* duplicate "body text" label to get the expand/collapse to be smooth. – DonMag Mar 24 '17 at 12:13
  • `tableView.beginUpdates()` `tableView.endUpdates()` This trick saved the day – geek1706 Jun 19 '20 at 05:51