Reputation: 1672
I have a View which has two labels and a Table View inside it. I want label 1 to always stay above my Table View and label 2, to be below the Table View. The problem is that the Table View needs to auto-size meaning either increase in height or decrease.
Right now I have a constraint saying the Table View's height is always equal to 85 and a @IBOutlet
to the height constraint where i'm able to change the constant.
I'm guessing I need to change the constant to the height of all the cells, but i'm not sure how.
Upvotes: 45
Views: 53800
Reputation: 129
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let contentheight = tableView.contentSize.height
self.tableHeightConstraint.constant = contentheight
}
Upvotes: 0
Reputation: 816
The below code worked for me.
- Create an outlet for tableViewHeight.
@IBOutlet weak var tableViewHeight: NSLayoutConstraint!
var tableViewHeight: CGFloat = 0 // Dynamically calcualted height of TableView.
- For the dynamic height of the cell, I used the below code:
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView.estimatedRowHeight
}
- For height of the TableView, with dynamic heights of the TableView Cells:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
print(cell.frame.size.height, self.tableViewHeight)
self.tableViewHeight += cell.frame.size.height
tableViewBillsHeight.constant = self.tableViewHeight
}
Explanation:
After the TableView cell is created, we fetch the frame height of the cell that is about to Display and add the height of the cell to the main TableView.
Upvotes: 5
Reputation: 324
A more modern way is doing this:
override func updateViewConstraints() {
tableView.heightAnchor.constraint(equalToConstant: tableView.contentSize.height).isActive = true
super.updateViewConstraints()
}
Upvotes: 0
Reputation: 1028
For TableView Height adjustment automatically with its content size use this in ViewController class.
//constraintTableViewHeight :- tableview height constraint
override func viewWillLayoutSubviews() {
super.updateViewConstraints()
self.constraintTableViewHeight.constant = self.tableView.contentSize.height
}
and also add this
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
self.viewWillLayoutSubviews()
}
This code easily adjust tableview height automatically with its content size.
Upvotes: -1
Reputation: 1081
There is another way to do that.
You can add an observer on table view contentSize
variable, and self size when change in table view content.
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var tableHeightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
tableView.layer.removeAllAnimations()
tableHeightConstraint.constant = tableView.contentSize.height
UIView.animate(withDuration: 0.5) {
self.updateViewConstraints()
}
}
Upvotes: 63
Reputation: 468
Extending @nova answer to swift 4
tableViewSizeObservation = tableView.observe(\.contentSize) { [weak self] (tableView, _) in
tableView.layer.removeAllAnimations()
self?.tableViewHeightContraint.constant = tableView.contentSize.height
UIView.animate(withDuration: 0.5) {
self?.view.updateConstraints()
self?.view.layoutIfNeeded()
}
}
deinit {
tableViewSizeObservation?.invalidate()
}
Upvotes: 0
Reputation: 17902
In Swift 4.2 and Xcode 10.1
Here you have two options to set height for UITableView based on content dynamically.
1) If you get content size use this code in viewDidLayoutSubviews()
DispatchQueue.main.async {
var frame = self.TblView.frame
frame.size.height = self.TblView.contentSize.height
self.TblView.frame = frame
}
2) Based on table view height constraint update table view height. After got the response from server when reload table view write this code.
DispatchQueue.main.async {
self.TblViewHeightConstraint.constant = CGFloat((self.array.count) * 30)//Here 30 is my cell height
self.TblView.reloadData()
}
Upvotes: 1
Reputation: 27620
You have to override updateViewConstraints()
in your UIViewController and set the height constraint's constant to tableView.contentSize.height:
override func updateViewConstraints() {
tableHeightConstraint.constant = tableView.contentSize.height
super.updateViewConstraints()
}
Then you have to make sure that Label2
has a top constraint that is greaterThanOrEqual
to the table view's bottom. And you also have to change the table view's height constraint's priority from Required
to High
to avoid conflicting constraints when the table view's contentHeight
is larger than the available height.
Upvotes: 66