UITableViewCell auto height based on amount of UILabel text - ios

I have a bit of a tricky set up in my storyboard, I have a UIViewController that holds a UITableViewController. Within the UITableViewController I have several prototypecells I have linked to subclassed uitableviewcell objects in code.
Using constraints and storyboard I would like to change the height of my prototype cell depending on the size the UILabel ends up being which is dependant on the text going into it.
Currently I have a
UIViewController
-- UITableViewController
-- -- UITableViewCell ((melchat) prototype cell)
-- -- -- ContentView
-- -- -- -- UIView ((background) view with drop shadow card type effect)
-- -- -- -- -- UIImageView (Avatar)
-- -- -- -- -- IUlabel (dynamic (depending on code/input) multi line UILabel)
Some how I would like the UILabel to resize the UIView (background) then in turn effect the height of that UITableViewCell.
I am using XCode 8.2.1
I have taken a screen shot of the layout in storyboard and constraints applied.
Update
I have updated my constraints to pretty much all go back to ContentView and have updated uilabel line count to 0 and then also implemented the UITableViewAutomaticDimension code but its still not working. Please see code and screen shots below.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}

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

Use UITableViewAutomaticDimension
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

step1:Give below constraint to UIView that is inside to the contentView.
Leading constraint to contentView
Top constraint to contentView
Bottom constraint to contentView
Trailing constraint to contentView
step2: Give below constraint to UIlabel
Leading constraint to UIImageView
Top constraint to UIView
Bottom constraint to UIView
Trailing constraint to UIView
step3: Then select your Trailing constraint of IUlabel and select edit option and then select constant and select greaterThanEqual option.
step4: set label's numberofline = 0
step5: Add this code into viewDidLoad()
yourtableview.estimatedRowHeight = 80.0
yourtableview.rowHeight = UITableViewAutomaticDimension

Swift 4.2 and 5. As mention above you can set UITableView object property or
tblView.rowHeight = UITableView.automaticDimension
tblView.estimatedRowHeight = 300
you can also define the same by implementing UITableViewDelegate methods
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 300
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}

After populating the UILabel and applying constrains, get the height of the label and set it as the height of the UIView.
After that call -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath and pass the height of the UILabel/UIView so that it gets the actual height for that row

Related

Tableview not getting Xib files height

I have created 3 custom .xib files for my tableview.
But i am not able to figure out to specify the height of each cell.
I have implemented above line in viewdidLoad()
tableview.estimatedRowHeight = 120
tableview.rowHeight = UITableView.automaticDimension
I have just put a uiview in each of .xib file with 4 contraints (leading, trailing, top, bottom)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
But it's not setting proper height to my cells.
its only when I hard code the value, only then it works.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
How to handle this problem, as data will soon become dynamic and I can't be changing these hardcoded value.
UIView has not height value by default. As you trying it this will not set the height of cell.
You can try by placing a UILabel or UIButton inside the UIView on which you have settled the 4 constraints (leading, trailing, top, bottom).
NOTE: UILabel or UIButton also need 4 constraints (leading, trailing, top, bottom) if you want automatic height of UITableViewCell.
Replace your UIView with UILabel and set number of lines to zero, Then it will automatically take the height based on the content of UILabel

Adjust UILabel Dynamically Within UITableViewCell?

I would like to adjust the number of lines in a UILabel dynamically. For example, there could be a long string or a short string. If there are less than 10 characters, there should be one line. If there are 10-20 characters, it should be two lines. This UILabel is inside of a UITableViewCell. Currently, if there is a long string, then the UILabel just shows "..." wherever it runs out of space, so the string is cut off. How can I prevent this from happening?
Try:
nameOfLabel.numberOfLines = 0
0 is supposed to be dynamic.
Constaints from Top Left Right Buttom of label and label.numberOfLine = 0 make it dynamically resizable according to dynamic content.
First set numberOfLines to 0 for that UILabel from Storyboard
Than set estimated height for your UITableView
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 108.0
Than Add heightForRowAt method
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Hope it Help!
Assign and implement tableview dataSource and delegate
Assign UITableViewAutomaticDimension to rowHeight & estimatedRowHeight
Implement delegate/dataSource methods (i.e. heightForRowAt and return a value UITableViewAutomaticDimension to it)
-
Objective C:
// in ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property IBOutlet UITableView * table;
#end
// in ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.table.dataSource = self;
self.table.delegate = self;
self.table.rowHeight = UITableViewAutomaticDimension;
self.table.estimatedRowHeight = UITableViewAutomaticDimension;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
Swift:
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Don't forget to set dataSource and delegate for table
table.dataSource = self
table.delegate = self
// Set automatic dimensions for row height
table.rowHeight = UITableViewAutomaticDimension
table.estimatedRowHeight = UITableViewAutomaticDimension
}
// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
For label instance in UITableviewCell
Set number of lines = 0 (& line break mode = truncate tail)
Set all constraints (top, bottom, right left) with respect to its superview/ cell container.
Optional: Set minimum height for label, if you want minimum vertical area covered by label, even if there is no data.
Note: If you've more than one labels (UIElements) with dynamic length, which should be adjusted according to its content size: Adjust 'Content Hugging and Compression Resistance Priority` for labels which you want to expand/compress with higher priority.
You need to give constraints to tableview cell's label leading, trailing, top and bottom like below...
Also set label's number of lines to zero and line breaking mode to word wrap.
And in your main view controller just add this line...
self.tableView.estimatedRowHeight = UITableViewAutomaticDimension
The above line automatically calculates the cell height as per its content.

Autosizing Cells Not Working in iOS 11

I am populating my UITableView from a web service. Here are all the constraints. Some of the items like Cheese Burgers has 10 lines of text which is not displayed.
And here is the result:
To enable automatic resizing of your UITableViewCell, set the rowHeight and estimatedRowHeight of your UITableView in your controller's viewDidLoad() method, like so:
self.tableView.estimatedRowHeight = 150.0
self.tableView.rowHeight = UITableViewAutomaticDimension
And then if you would like or you need to implement the heightForRow UITableViewDelegate method, don't forget to pass again the UITableViewAutomaticDimension to whatever row or section that needs an auto resizing cell, like so:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let section = indexPath.section
if let itemSection = ItemTableViewSections(rawValue: section) {
switch itemSection {
case .header: return 80.0
case .photos: return 95.0
case .note: return UITableViewAutomaticDimension
case .rejectOptions: return 50.0
}
}
return 0
}
Lastly, don't forget to select an answer if an answer really answers your question just like in your last question :)
EDIT: I made a sample project that uses Storyboard and targeting merely iOS 11. All works fine. Just don't forget to set your label's constraint - top, bottom, leading, and trailing. These constraints will be required for autoresizing cell. Lastly, set the UILabel's number of lines to 0.
increase Vertical Content Hugging Priority by 1 of UILabel
When all else fails, try setting Content Compression Resistance Priority to 1000. That's how I fixed my problem.

how to increase the label size according to text in static table view in swift 3

I have 3 custom cells in Static TableView. All cells have different heights. But I need to make height of newsDetail label dynamic according to its content size. It was easy to make dynamic for dynamic tableview by setting rowHeight and estimatedRowHeight. But it didn't work out for Static TableView. I searched but couldn't find solution for this, anyone please could help me in swift 3?
If you are using Autolayout you need to use,
In viewDidLoad() provide estimated height
tableView.estimatedRowHeight = 60.0 //you can provide any
tableView.rowHeight = UITableViewAutomaticDimension
Implement Delegate method
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension;
}
Need to provide constraint on your label in UITableViewCell.
Top, Bottom, Trailing, Leading and no need to provide any fix height constraint.
And make numberOfLines to 0 of UILabel

I need to set UITableViewCell Dynamic Height, With Multiple dynamic label with UIImageView

I need to set UITableViewCell dynamic height based on it's content.
Here is my demo image:
In this to label which have dynamic content so based on that label content my cell height should change..
I get the constraint error. In this cell two UILabel is available and both have dynamic content size. (I already make the demo with auto resizing cell with only one label.) But in this cell two label are there. So error is xcode suggest me to give Y POS or Height to label, but I already set top constraints. (4 side constraints with label line set to 0 Zero) But still it's fails.
I also try with this code
self.tableView.estimatedRowHeight = 250.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
Here is my demo code
Look at the screenshot of my output. For both the labels , you should give all the four constrains and you have to change the heights of both the labels priority to 750 & set the hugging and resistance priority to 1000. Then you have to change the number of lines to 0 in storyboard
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 250
}
Add this code into viewDidLoad() method:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
In Swift 3, Use
func tableView(_ tableView: UITableView,estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return HEIGHT // Maximum cell height
}
In table view cell, Set dynamic height constraint to the text view (Greater than or equal) - Maximum text view height
I found the problem. After setting text to UILabel, it doesn't still set correct height frame to its content. In cellForRowAt, just add this:
//these make height frame both of labels became correct
cell.lbName.sizeToFit()
cell.lbAge.sizeToFit()
// update cell layout
cell.layoutIfNeeded()
Have a look at the UITableViewDelegate function tableView(_:heightForRowAt:). It’ll work in your case if you are able to calculate the height for a given index path.

Resources