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
.
Set the numberOfLines
property of UILabel
s to 0(zero).
Set the Distribution of the UIStackView
as Fill
Then, in your tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
method hide the labels. And it will automatically handle the spaces between UILabel
s
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:
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
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:
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
}
Related Topics
Accessing iOS Safari Web Inspector from Windows MAChine
Flutter iOS Build Failed an Error of Pod Files: Podfile Is Out of Date
Swift - Coredata Migration - Set New Attribute Value According to Old Attribute Value
iOS Glsl. How to Create an Image Histogram Using a Glsl Shader
Determine Mime Type from Nsdata
Crashlytics iOS - Log Caught Exception
Setting Maximum Number of Characters of 'Uitextview ' and 'Uitextfield '
Perform Push Segue After an Unwind Segue
Loading a Resource (E.G. Storyboard) in a Swift Framework
Text Color Based on Background Image
Swift: Testing Optionals for Nil
Xcode Is Creating Generic Xcode Archive Instead of iOS App Archive
Remembering Scroll Position on Uitableview
How to Check If Device Can Make a Phone Call (iOS 8)
How to Concatenate Nsattributedstrings
React Native iOS Build:Can't Find Node
Facebooksdk and Bolts Conflicting Each Other (Duplicate Symbols) on Build