UITableViewCell + Dynamic Height + Auto Layout
Asked Answered
T

2

4

I came from this great answer:
Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

I've implemented the things described in that answer but I'm facing with a little different scenario. I haven't one UILabel but instead I have a dynamic list of UILabels.

I've created an image showing some different cases of what the table view should look:

enter image description here

At the current state of the repo the cell doesn't grow vertically to fit the cell's contentView.


UPDATE

REPO: https://github.com/socksz/DynamicHeightCellAutoLayout

If you try to get the project from the repo and run it, you can see exactly what is the problem I'm referring. I can't get what is missing for let it works.

Tattered answered 15/12, 2013 at 18:17 Comment(2)
The question you're asking now is specifically about which constraints to add. In order to figure this out, you need to describe the "rules" of how you want the layout to work. Can you explain a little more of what you mean by "labels need to shrink if their content is too long"? Does that mean you want the font size to shrink, or only 1 line of text allowed per label, or what? More importantly, since you're dealing with table view cells and row heights, do you always want the cells to grow vertically to fit every label, regardless of how many?Yseulta
@smileyborg: Yep, I want the cells grow vertically to fit every label, regardless of how many. The shrink stuff it works because every label has adjustsFontSizeToFitWidth property set to YES. If you've run the project you've seen that the cell doesn't grow vertically to fit the contentView unfortunately.Tattered
Y
3

The problem here is with the third party component you are using, FXLabel, not with any of the code around table views or Auto Layout in them. In order to support Auto Layout, custom subclasses of UIView must implement the -[intrinsicContentSize] method appropriately, and then call -[invalidateIntrinsicContentSize] when something changes it.

In this case, FXLabel appears to be relying on its superclass implementation (UILabel) for the above methods, and since UILabel was not designed to handle variable line spacing in the way that FXLabel implements it, it doesn't know the correct intrinsicContentSize to return, and therefore the Auto Layout calculations are wrong (in this case, since the intrinsic content size is too small). Check out the "Enabling Custom Views for Auto Layout" section of this excellent obcj.io article for more details.

Now the good news is that as of iOS 6, you should be able to accomplish this using an attributed string in a standard UILabel. Check out the Stack Overflow answer here.

If for some reason you really like FXLabel, perhaps you could open an issue on the GitHub project (or try and fix it yourself and submit a pull request).

Yseulta answered 15/12, 2013 at 19:46 Comment(3)
By the way, you can do a simple test to verify that the issue lies with the FXLabel component by setting it up with default line spacing, checking the value of the intrinsicContentSize property, then increasing the line spacing and re-checking the value of the intrinsicContentSize property. I'll bet it remains the same.Yseulta
I don't use FXLabel anymore because I don't need the line spacing anymore. Sorry that I don't told you. I'm updating the question with more details and code.Tattered
I've updated the question with a simple repo showing the problem! :DTattered
T
1

To set automatic dimension for row height & estimated row height, ensure following steps to make, auto dimension effective for cell/row height layout.

  • Assign and implement dataSource and delegate
  • Assign UITableViewAutomaticDimension to rowHeight & estimatedRowHeight
  • Implement delegate/dataSource methods (i.e. heightForRowAt and return a value UITableViewAutomaticDimension to it)

-

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

    // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension

}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension
}

For label instance in UITableviewCell

  • Set number of lines = 0 (& line break mode = truncate tail)
  • Set all constraints (top, bottom, right left) with respect to its superview/ cell container.
  • Optional: Set minimum height for label, if you want minimum vertical area covered by label, even if there is no data.

enter image description here

Tiphanie answered 11/10, 2017 at 11:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.