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.
Related
I'm trying to create a tableview cell to accommodate texts with varying lengths and I need each cell to have a dynamic height. I've tried using the below but no show:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 410
Can anybody help me please?
To set automatic dimension for row height & estimated row height, ensure following steps to make, auto dimension effective for cell/row height layout. I just tested following steps and code and works fine.
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)
-
#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.
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.
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
I'm having a UITableView. In that I have a single label. I am doing following for label:
Set number of lines to zero
Set top space to container margin
Set bottom space to container margin
My contents for UILabel may vary, some time it may have 3 lines, some times 10 lines etc. My problems is it displays only 2 rows. How to adjust the height of cell so that UILabel will show the whole contents.
Thanks in advance.
You should set numberoflines to 0. Provide either leading & trailing space constraints for your label or fixed width constraint along with top & bottom space constraints. Then use tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
set your label's constraint with cell like top bottom leading and trailing, set number of line for labels to zero and line break mode to word wrap. now place this two tableView methods to calculate cell height dynamically.
For Swift 3.0
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
for Objective C
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
so it will take cell size dynamically as you want.
hope this will help you.
I am using automatically resizing cells in my project. I want to keep the cells at a minimum height, but I cannot set a minimum height constraint for my cells in my Content View (as it is greyed out in the Add New Constraints view:
Is there anyway to add minimum height constraints for my cells?
When UITableViewAutomaticDimension is enabled the system calls UITableViewCell's systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: method to calculate the cell height, so you can subclass UITableViewCell and override this method to force a minimum height for the cell, in this way
class MinHeightTableViewCell: UITableViewCell {
var minHeight: CGFloat?
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
guard let minHeight = minHeight else { return size }
return CGSize(width: size.width, height: max(size.height, minHeight))
}
}
And then
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "minHeightCell", for: indexPath) as! MinHeightTableViewCell
cell.minHeight = 62 // change with your desidered min height
cell.textLabel?.text = "some text"
return cell
}
set a height constraint as height >= 60.0 No need to do anything
I added this constraint to my cell but in code (swift)
contentView.heightAnchor.constraint(equalToConstant: 80).isActive = true
If your cell view needs more space:
contentView.heightAnchor.constraint(greaterThanOrEqualToConstant: 80).isActive = true
Here's code used in viewDidLoad. cell is the UITableViewCell. Notice the relatedBy parameter is >=. 44 is my minimum height...
[cell.contentView addConstraint: [NSLayoutConstraint constraintWithItem: cell.contentView attribute: NSLayoutAttributeHeight relatedBy: NSLayoutRelationGreaterThanOrEqual toItem: nil attribute: NSLayoutAttributeNotAnAttribute multiplier: 1 constant: 44]];
You can makes your cells as dynamic height by returning the UITableViewAutomaticDimension in height calculation methods of tableview. But for this your cell design constraints should be like the below one
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
Note: Todo Title is the static height. And description will be dynamic height. So description does not own the height constrain. Important thing is you need set a number of lines as 0 for description label
simple added height constraint with minimum height you want and then change it relation to "Greater then Equal to". look highlighted section of screen short.
Follow these steps, to set automatic dimension for cell with some minimum height.
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.
Note: Set minimum height for label, if you want minimum vertical area covered by label, even if there is no data.