Dynamic Uitableview Cell Height Based on Contents

Dynamic UITableView Cell Height Based on Contents

The best way that I've found for dynamic height is to calculate the height beforehand and store it in a collection of some sort (probably an array.) Assuming the cell contains mostly text, you can use -[NSString sizeWithFont:constrainedToSize:lineBreakMode:] to calculate the height, and then return the corresponding value in heightForRowAtIndexPath:

If the content is constantly changing, you could implement a method that updated the array of heights when new data was provided.

UITableViewCell auto height based on amount of UILabel text

To go a little further on Dao's answer..

He is correct, you need to use UITableViewAutomaticDimension

Also, you need to ensure that you setup your constraints in a way that all of the content in the cell is constrained to the cells contentView. So your label will likely need constraints such as

  • Leading constraint to ImageView
  • Top constraint to contentView
  • Bottom constraint to contentView
  • Trailing constraint to contentView

Make sure that you set the UILabel to multiline (or lines = 0) and it should work.

If you are using the heightForRowAt delegate functions ensure you return UITableViewAutomaticDimension

How to use dynamic height of UITableViewCell in auto-layout and move other views to up when bottom view is hidden?

At first, make the height of UITableViewCell to UITableView.automaticDimension

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}

Embed all of your questionLabels in a UIStackView (vertical) excluding bottomLabel. Set AutoLayoutConstraint between UIStackView and bottomLabel.

Sample Image

Set the numberOfLines property of UILabels to 0(zero).

Sample Image

Set the Distribution of the UIStackView as Fill

Sample Image

Then, in your tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell method hide the labels. And it will automatically handle the spaces between UILabels

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

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

cell.questionLabel1.text = labelOneText[indexPath.row]
cell.questionLabel2.text = labelTwoText[indexPath.row]
cell.questionLabel3.text = labelThreeText[indexPath.row]

if labelOneText[indexPath.row] == "" {
cell.questionLabel1.isHidden = true
}

if labelTwoText[indexPath.row] == "" {
cell.questionLabel2.isHidden = true
}

if labelThreeText[indexPath.row] == "" {
cell.questionLabel3.isHidden = true
}

return cell
}

Final Output:

Sample Image

Dynamic UITableView height

You need to set an IBOutlet to the NSLayoutConstraint that sets the tableView height (first you need create the height constraint with any value, doesn't matter) and then ctrl drag it to your class file

Sample Image

Then in your viewWillAppear you have to calculate the tableView height and set it. Like this:

var tableViewHeight:CGFloat = 0;
for (var i = tableView(self.tableView , numberOfRowsInSection: 0) - 1; i>0; i-=1 ){
tableViewHeight = height + tableView(self.tableView, heightForRowAtIndexPath: NSIndexPath(forRow: i, inSection: 0) )
}
tableViewHeightLayout.constant = tableViewHeight

And that's pretty much it. That will give your scrollView content size and shouldn't raise any warnings.

How to get height of UITableView when cells are dynamically sized?

I finally hacked out a solution:

tableView.contentSize.height will not work for dynamic cells because they will only return the number of cells * estimatedRowHeight.

Hence, to get the dynamic table view height, you look for all visible cells, and sum up their heights. Note that this only works for table views that are shorter than your screen.

However, before we do the above to look for visible cells, it is important to know that note we need to get the table view on the screen so that we can obtain visible cells. To do so, we can set a height constraint for the table view to some arbitrarily large number just so it appears on the screen:

  1. Set height of table view constraint:

    // Class variable heightOfTableViewConstraint set to 1000
    heightOfTableViewConstraint = NSLayoutConstraint(item: self.tableView, attribute: .height, relatedBy: .equal, toItem: containerView, attribute: .height, multiplier: 0.0, constant: 1000)
    containerView.addConstraint(heightOfTableViewConstraint)
  2. Call tableView.layoutIfNeeded(), and when completed, look for the visible cells, sum up their height, and edit the heightOfTableViewConstraint:

    UIView.animate(withDuration: 0, animations: {
    self.tableView.layoutIfNeeded()
    }) { (complete) in
    var heightOfTableView: CGFloat = 0.0
    // Get visible cells and sum up their heights
    let cells = self.tableView.visibleCells
    for cell in cells {
    heightOfTableView += cell.frame.height
    }
    // Edit heightOfTableViewConstraint's constant to update height of table view
    self.heightOfTableViewConstraint.constant = heightOfTableView
    }


Related Topics



Leave a reply



Submit