Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 964
leonardloo Avatar asked Oct 17 '16 06:10

leonardloo


3 Answers

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
    }
    
like image 195
leonardloo Avatar answered Oct 18 '22 05:10

leonardloo


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
                }
            }
        }
    }
like image 39
Shubham Singh Avatar answered Oct 18 '22 06:10

Shubham Singh


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!!!

like image 4
Ebed Kharistian Avatar answered Oct 18 '22 04:10

Ebed Kharistian