How to Get Height of Uitableview When Cells Are Dynamically Sized

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
    }

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.

UITableView with dynamic height

You need to use intrinsicContentSize variable of a UITableView.
intrinsicContentSize will give us table height.

Create a subclass for child tableView and override
intrinsicContentSize.

Dynamic row heights of a UITableView inside a UITableViewCell

Setting the height of the UITableView when the height of the cells is dynamic

You can try this

// add observer to your tableView to get its proper height when its 
//data is loaded. you can do this in view did load
self.YourTableView.addObserver(self, forKeyPath: "contentSize",options: .new, context: nil)

// override this metod to observe for tableView height change
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?){
if(keyPath == "contentSize"){

if let newvalue = change?[.newKey]
{
let newsize = newvalue as! CGSize
// make height constraint for your table view and set to new size.
// and here you can check if newSize.height is more than required tha you can set it to default
if(newsize.height < defaultHeight)
self.tableViewHeightConstraint.constant = newsize.height

}else{
self.tableViewHeightConstraint.constant = defaultHeight

}
}
}

Let me know if you face any trouble

And remember to remove observer otherwise app will crash

deinit {
self.YourTableView.removeObserver(self, forKeyPath: "contentSize")
}

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



Related Topics



Leave a reply



Submit