Multiple line UIlabel in UItableviewcell using Autolayout - ios

I have set setMaXPreferredLayoutWidth to UILabel and added all the required constraints to the UIlabel now I can see multiline UIlabel in my UItableviewcell but my problem is I am getting extra padding at the top and bottom of my UIlabel based on MaxpreferredLayoutWidth value.
When I set the MaxPreferreLayoutWidth to 200 I get this
When I set the MaxPreferreLayoutWidth to 100 I get this
In general UIlabel height depends based on preferredMaxLayoutWidth.
Can any one say me how to remove this extra padding and render the exact height of UIlabel?

Try this code,
CGSize suggestedSize = [textWithMultipleLines sizeWithFont:myLabel.font constrainedToSize:CGSizeMake(width, FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping];//here "width" is the maximum acceptable width of myLabel
CGRect labelFrame = myLabel.frame;
labelFrame.size = suggestedSize;
[myLabel setFrame:labelFrame];
and in
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
{
//get the string assigned to label
CGSize suggestedSize = [stringAssignedToLabel sizeWithFont:myLabel.font constrainedToSize:CGSizeMake(width, FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
return suggestedSize.height+5;
}

The simplest way to this is to extend your own UITableViewCell class, and create a UILabel there, also create a public getMethod:
Interface:
- (CGFloat)getLabelHeight;
Implementation:
- (CGFloat)getLabelHeight {
return label.frame.size.height
}
TableView File:
-(CGFloat)heightForRowAtIndexPath {
return [cell getLabelHeight]
}
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath)indexPath {
your_cell_instance = [[Your_Cell_Class alloc]initWithTableViewCellStyle:UITableViewCellStyleDefault andReuseID:your_reuse_id];
your_cell_instance.text = #"Your Long Text"
[your_cell_instance setNumberOfLines:0];
[your_cell_instance sizeToFit];
return your_cell_instance;
}
Its important to set first the text of the label and then // number of lines and sizeToFit //
And you need to reload the tableView data in proper of your time
I Haven't time to test it, but i hope it works.

We have to set the tableviewcell's frame while calculating the height of the cell in heightForRowAtIndexPath
Ex:
[tableViewCell setFrame:CGRectMake(0, 0, CGRectGetWidth(self.tableView.bounds), CGRectGetHeight(tableViewCell.bounds))];
and then in layoutSubviews method of UItableviewcell we have to set the preferredMaxLayoutwidth
Ex:
[self.multilineLabel setPreferredMaxLayoutWidth:CGRectGetWidth(self.bounds)];

Related

How to change the height of a custom cell individually within a UITableView?

I am trying to change the height of each cell individually based on how long my UILabel is, but it does not seem to change.
I have found the following question: How to change cell height dynamically in UITableView static cell
I tried the solution from that question:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//return 110;
NewsFlashCustomCell *cell;
static NSString *CellIdentifier = #"CustomCell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[cell layoutIfNeeded];
return cell.messageLabel.frame.origin.y + cell.messageLabel.frame.size.height;
}
However, that seems to do nothing.
Here's a screenshot:
I'd like the height of the cells containing "tidal wave" and "mashup" to be smaller than the last 2 cells since it has a longer message.
I cannot perform a indexPath.row check to change each cell individually because each message is pulled from a database, so the length of the message varies.
What can be done?
In case it helps, here's a screenshot of my constraints:
Thanks.
UPDATE:
I added the following code in viewDidLoad:
tableView.rowHeight = UITableViewAutomaticDimension;
This is what it looks like:
If you can't set try with other method reduce the label font size depend upon the cell height .
label.numberOfLines=0;
label.clipsToBounds=YES;
label.adjustsFontSizeToFitWidth=YES;
label.lineBreakMode = NSLineBreakByWordWrapping;
You can calculate height for label from its length of text and do it like following way:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return [self calculateHeightForCellAtIndexPath:indexPath];
}
#pragma mark - cell height handling
-(CGFloat)calculateHeightForCellAtIndexPath:(NSIndexPath *)indexP{
UILabel *lbl = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width-22, defaultHeightOfYourLabel)];
NSString *strLbl;
strLbl = [yourArray objectAtIndex:indexP.row];
lbl.text = strLbl;
if (IS_IPAD) {
[lbl setFont:fontRegular15];
}else{
[lbl setFont:fontRegular12];
}
UIFontDescriptor * fontDLBLTime = [lbl.font.fontDescriptor
fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold];
if (IS_IPAD) {
[lbl setFont:[UIFont fontWithDescriptor:fontDLBLTime size:15]];
}else{
[lbl setFont:[UIFont fontWithDescriptor:fontDLBLTime size:12]];
}
[lbl setLineBreakMode:NSLineBreakByClipping];
[lbl setNumberOfLines:0];
int noOfLines = [GlobalFunction lineCountForLabel:lbl];
CGFloat height = [GlobalFunction heightForWidth:lbl.frame.size.width usingFont:lbl.font forLabel:lbl];
if (noOfLines>1) {
return height + 33; //here 33 is sum of top and bottom space from view.
}
return 50; //default height of cell.
}
In your class implement following methods:
#define CGFLOAT_MAX_HEIGHT 2000.0
+ (int)lineCountForLabel:(UILabel *)label {
return ceil([self heightForWidth:label.frame.size.width usingFont:label.font forLabel:label] / label.font.lineHeight);
}
+(CGFloat)heightForWidth:(CGFloat)width usingFont:(UIFont *)font forLabel:(UILabel *)lbl{
NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
CGSize labelSize = (CGSize){width, CGFLOAT_MAX_HEIGHT};
CGRect r = [lbl.text boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName: font} context:context];
return r.size.height;
}
You can customize lbl on basis of your font and label size.
Have your label constrain the bounds of your cell, like your already doing. Be sure to include padding around it so it looks nicer.
In your heightForRowAtIndexPath: calculate the height required for your label (it is important you have your label correctly configured for multiline and/or word wrapping)
Calculate the required height of label
CGRect frame = [label.text boundingRectWithSize:CGSizeMake(cell.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName: font} context:nil];
Return the calculated height plus padding
frame.size.height + TopPadding + Bottom Padding
This is a general approach to have a dynamically sizing cell.
Note: Sometimes this is off by a few points so you may need to add up 5 extra points in the cell height to get all the text fitting in the label.
Please write following line in viewDidLoad:
_tableView.rowHeight = UITableViewAutomaticDimension;
Please make sure of following points:
Dont create height constraint of label
Make width of that label equal to screen size or content view
Apply leading, trailing, top and bottom constraint
Dont write heightForRowAtIndexPath method
Please let me know the results
EDIT :
Write following line in your cellForRowAtIndexPath method
myLabel.preferredMaxLayoutWidth = cell.contentView.frame.size.width;

Having 2 multiline labels on single UITableViewCell in iOS 8

I have a scenario in which a single UITableViewCell have 2 UILable. I can have long text in it coming from server which causes both labels to be multiline at same time.
I have implemented autolayout and
label.numberofline = 0;
tableVieww.estimatedRowHeight = 100.0;
tableVieww.rowHeight = UITableViewAutomaticDimension;
but it results only one label to expand not both. Please help.
Thanks in advance
try this:
use this code to calculate row height
Note : ExtraHeight"H"
Suppose you have cell with height 100 and in that cell a label has height 20 than extra height will be 80, because this code is calculating the height of label as per text with its size.
you are going to put this code in heightforRowatindexpath so cell.label can't get there so just pass the text and use Method-2
Method - 1:
-(CGFloat)setRowHeightWithLabel:(UILabel *)lbl withLabelText:(NSString *)lblText withExtraHeight:(CGFloat)H withFont:(CGFloat)fontSize
{
CGFloat totalHeight;
CGFloat lblWidth = lbl.frame.size.width;
CGSize lblTextSize = [lblText boundingRectWithSize:CGSizeMake(lblWidth, MAXFLOAT)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName: [UIFont systemFontOfSize:fontSize]} context:nil].size;
if (lblTextSize.height > lbl.frame.size.height) {
totalHeight = (lblTextSize.height+H);
}
else
{
totalHeight = lbl.frame.size.height+H;
}
NSLog(#"+++++++++++++Height - %.2f",totalHeight);
return totalHeight;
}
Use this for use in heightforRow method
Method - 2:
-(CGFloat)setRowHeightWithLabelText:(NSString *)lblText withExtraHeight:(CGFloat)H withFont:(CGFloat)fontSize
{
CGFloat totalHeight;
CGFloat lblWidth = 300;
CGSize lblTextSize = [lblText boundingRectWithSize:CGSizeMake(lblWidth, MAXFLOAT)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName: [UIFont systemFontOfSize:fontSize]} context:nil].size;
if (lblTextSize.height > 20) {
totalHeight = (lblTextSize.height+H);
}
else
{
totalHeight = 20+H;
}
NSLog(#"+++++++++++++Height - %.2f",totalHeight);
return totalHeight;
}
I think you are using autolayout I had the same problem I resolved it by setting maximum width of labels and the in label's size Inspector you should set preferred width to your max width
What You have so far looks fine. That should work without the need calculate the label height as some suggested.
Just make sure that you have the proper constraints on your labels.
Top constraint between the top label and its superview.
Bottom constraint between the bottom label and its superview.
A vertical spacing constraint between the two labels.
I tested it. it's working!
- (void)viewDidLoad {
[super viewDidLoad];
dynamicTableVuew.rowHeight = UITableViewAutomaticDimension;
dynamicTableVuew.estimatedRowHeight = 100;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellId"];
UILabel *label1 = (UILabel *)[cell viewWithTag:1];
UILabel *label2 = (UILabel *)[cell viewWithTag:2];
label1.text = #"Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text";
label2.text = #"Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text Very long text";
return cell;
}
That's all I have in the view controller. and nothing special in storyboard.
One last thing to check. Make sure that your tableview is connected to your view controller with an outlet. You may see the outlet code there but does not mean its connected. maybe it was removed by mistake. the following lines will not take effect:
tableVieww.estimatedRowHeight = 100.0;
tableVieww.rowHeight = UITableViewAutomaticDimension;
If you want two labels to be multi-line (supposing you are using "Subtitle" cell type"), you must set numberOfLines to 0 to both labels, eg:
UITableViewCell cell = [UITableViewCell alloc]init];
cell.textLabel.numberOfLines = 0;
cell.detailTextLabel.numberOfLines = 0;
Your lines about cell height seems to be correct

Table cell label not wrapping last line in iOS7

I am getting very strange problem in my app. I am creating table view cell dynamically. And adjusting height of cell label according to content.
My problem is that my cell label is not showing last line after wrapping means if there are total three lines for my label then label shows only two lines. The code was working on iOS6 but on iOS 7 it is giving problem.
[labelCell.contentView bringSubviewToFront:labelCell.textLabel];
labelCell.textLabel.numberOfLines = 0;
labelCell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
NSString *fieldLabel = labelCell.textLabel.text;
CGSize textSize = [self sizeForLabelWithString:fieldLabel width:600.0f andIndexPath:indexPath];
float newHeight = textSize.height+22.0f;
labelCell.height = newHeight;
use this method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *fieldLabel = labelCell.textLabel.text;
CGSize textSize = [fieldLabel sizeWithFont:[UIFont fontWithName:#"Georgia" size:17.0f] constrainedToSize:CGSizeMake(600, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
float newHeight = textSize.height+22.0f;
return newHeight;
}
Add below code to cellForRowAtIndexPath
UILabel *lblfield=[[UILabel alloc] init];
NSString *fieldLabel=[NSString stringWithFormat:#"%#",labelCell.textLabel.text];
CGSize textSize = [fieldLabel sizeWithFont:[UIFont fontWithName:#"Georgia" size:17.0f] constrainedToSize:CGSizeMake(600, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
float newHeight = textSize.height+22.0f;
lblfield.frame=CGRectMake(10, 0, 600, newHeight);
lblfield.backgroundColor=[UIColor clearColor];
lblfield.text=strusername;
[cell addSubview:lblfield];
I was having the same issue and just stumbled across this. My label was resizing to the correct size, but it wasn't showing the last line on any labels that wrapped to several lines. Moreover, when I selected/unselected the cell, I could suddenly see the last line.
I was able to resolve the issue by adding a small fudge factor (2 points) to the height of my cell. I updated the value to use for the height of the cell from:
return labelHeight + 2 * kTopAndBottomPadding;
to:
return labelHeight + 2 * kTopAndBottomPadding + 2.f;
You are changing the label height based on the content. So you need to handle the cell height dynamically or need to set the height of a cell based on the content(Max among the string.).
i.e
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return MAXStringHeght;
}
and try once.

UITableCell Height not adjusting properly

I have a UITableView that lists out the details of a certain item. Some of the details require more than one line to display properly.
I am using this code to dynamically resize the cell:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 1) return 320;
CGSize maxSize = CGSizeMake(280, MAXFLOAT);
CGSize cellSize = [[[appDelegate.callList objectAtIndex:callID] objectAtIndex:indexPath.row+1]
sizeWithFont:[UIFont systemFontOfSize:17]
constrainedToSize:maxSize
lineBreakMode:NSLineBreakByWordWrapping];
return cellSize.height+10;
}
It is a cell with Right Detail style. Nothing else. The detail textlabel is size 17 font.
Using this code, I get cells that cut off the cell below:
I know I could obviously just increase the +10 at the end, but then my cells would be too big for my liking.
Any help appreciated!
EDIT
I have found the issue. The width set in maxSize was too large.
Is there any way to find out the current detaillabel with without entering it manually prior?
Please refer below link, its an example of Dynamic Height UITableView Cells in Xcode: It may help you.
http://samrayner.com/posts/dynamic-tableview-cells/
You can use
CGSize maximumSize = CGSizeMake(300, 9999);
NSString *myString = #"This is a long string which wraps";
UIFont *myFont = [UIFont fontWithName:#"Helvetica" size:14];
CGSize myStringSize = [myString sizeWithFont:myFont
constrainedToSize:maximumSize
lineBreakMode:self.myLabel.lineBreakMode];
to calculate the displaying size of a givin NSString. So you can alter your cell's height according to the codes above. And also, you should reload your tableview after the heigth of some cell is changed.

Resize UITableViewCell to UILabel's height dynamically

I want to resize cell's height according to the label's height and label's height according to text. Or is there any way I can resize the cell's height according to the text entered in UITextView?
THIS METHOD IS DEPRECATED SINCE iOS 7.0.
There is a UITableView delegate method called heightForRowAtIndexPath that is called before you create a cell or a table.
You could use the NSIndexPath passed to it to get the text at a specific row and use the sizeWithFont method from UIStringDrawing.h to compute a CGSize for that row.
For example:
CGSize size = [text sizeWithFont:font
constrainedToSize:maximumLabelSize
lineBreakMode:UILineBreakModeWordWrap];
And finally you would return size.height.
--For iOS7--
Basing this off of Josh Vera's answer … place this in heightForRowAtIndexPath.
I have my table data stored in an NSArray *tableData.
// set the desired width of the textbox that will be holding the adjusted text, (for clarity only, set as property or ivar)
CGFloat widthOfMyTexbox = 250.0;
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get a reference to your string to base the cell size on.
NSString *cellText = [self.tableData objectAtIndex:indexPath.row];
//set the desired size of your textbox
CGSize constraint = CGSizeMake(widthOfMyTextBox, MAXFLOAT);
//set your text attribute dictionary
NSDictionary *attributes = [NSDictionary dictionaryWithObject:[UIFont systemFontOfSize:14.0] forKey:NSFontAttributeName];
//get the size of the text box
CGRect textsize = [cellText boundingRectWithSize:constraint options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
//calculate your size
float textHeight = textsize.size.height +20;
//I have mine set for a minimum size
textHeight = (textHeight < 50.0) ? 50.0 : textHeight;
return textHeight;
}
I haven't tested it for iOS<7, but I believe it should work for that as well.

Resources