I have a UITableView with cells that are dynamically sized. That means I have set:
tableView.estimatedRowHeight = 50.0
tableView.rowHeight = UITableViewAutomaticDimension
Now I want to get the height of the whole table view. I tried getting it through tableView.contentSize.height
but that only returns the estimated row height, and not the actual dynamic height of the table view.
How do I get the dynamic height of the whole table view?
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:
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)
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
}
Above mentioned solutions are pretty well. I tried a different approach & its smooth & clear to understand. Just Copy Paste the code & it will work.
override func viewDidLoad() {
super.viewDidLoad()
tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
}
override func viewWillDisappear(_ animated: Bool) {
tableView.removeObserver(self, forKeyPath: "contentSize")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "contentSize"{
if object is UITableView{
if let newValue = change?[.newKey]{
let newSize = newValue as! CGSize
heightOfTableViewConstraint.constant = newSize.height
}
}
}
}
it's already been answered, but I want to share my experience as well.
I have the same problem. I've searched answers in many similar questions and tried their answers and doesn't work.
Finally I've found leonardloo answer. Thanks a lot, but it doesn't solved my problem yet. I just want to complete his answer. I put this code from his answer:
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 }
in this block of code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
if indexPath.row == data.count-1{
// Insert the code here
}
return cell
}
It means after all the rows in table have been loaded, we update the height of the row using that piece of code. It works!!!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With