I have to solve some problems in existing project (Objective-C, Xcode 7.3, iOS).
Here I have a Table View in which I need to have some resizable cells to fit the content. The cells include Labels. The project uses UITableViewAutomaticDimension but it doesn't seem to work properly. The text in the cell goes beyond the right border.
So now i've checked some points:
The "Lines" property of the cell in Attributes Inspector is set to 0.
I have 4 constraints for the Label (pic related).
The heightForRowAtIndexPath method contains only return UITableViewAutomaticDimension;.
Here is the code, where UITableViewAutomaticDimension is used:
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.estimatedRowHeight = 50.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
Constraints screenshot <======
Try this
- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 186, 0)]; //max width that is allowed for label
lbl.numberOfLines = 0;
lbl.lineBreakMode = NSLineBreakByWordWrapping;
int GAP = 3;
float height = 0;
float fontSize = 14;
NSString *cellText = yourtext;
lbl.font= [ UIFont fontWithName:FONT_NAME_Ubuntu size: fontSize];
bl.text = cellText;
[lbl sizeToFit];
height += lbl.frame.size.height;
height += GAP;
return height;
}
Or try below one
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
for dynamic cell heigh according to the description display in cell
*/
NSDictionary *dict1 = (NSDictionary*)[array objectAtIndex:indexPath.row];
NSString *cellText = [dict1 valueForKey:#"test"];
UIFont *cellFont = [UIFont fontWithName:FONT_NAME_GOTHAM_4 size:11.0];
CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
return labelSize.height + 80;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
You need set in IB or in code
[yourLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis: UILayoutConstraintAxisVertical];
[yourLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis: UILayoutConstraintAxisVertical];
And after set the text call this
[cell setNeedsDisplay];
[cell layoutIfNeeded];
Hope this help. I took this from Self Sizing example from Apple
Related
I am using Autolayout and have a customised UITableViewCell that contains UITextView. The height of the cell and text view should be dynamically resized to accomodate larger contents.
Following answers from these links resize ui text view to its content and
dynamic ui text view, I have used a height constraint on the text view and set its value to the height of the content. This does the job of accommodating the textView, but it is overshooting the cell. I have tried options like adjusting the size of the cell also but none of them have helped. Surprisingly, sizeToFit seems to have no effect.
Here is the code I am using:
+ (SongAdditionalTextCell *)resize:(SongAdditionalTextCell *)additionalTextCell{
UITextView *textView = additionalTextCell.additionalText;
CGSize sizeThatFitsTextView = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, MAXFLOAT)];
NSLog(#"content height is %f, frame height is %f", textView.contentSize.height, textView.frame.size.height );
additionalTextCell.addnlTextHeightConstraint.constant = sizeThatFitsTextView.height;
return additionalTextCell;
}
Please see the attached image of the view (text view is second cell). any suggestions appreciated?
I use this one:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 2)
{
NSString *cellText = #"init some text";
CGSize labelSize = [self calculateTextSize:cellText];
return labelSize.height + 20.0f;
}
return 45;
}
- (CGSize) calculateTextSize: (NSString*) text
{
UIFont *cellFont = [UIFont fontWithName:#"HelveticaNeue" size:12.0];
CGFloat width = CGRectGetWidth(self.tableView.frame) - 40.0f;
CGSize constraintSize = CGSizeMake(width, MAXFLOAT);
CGRect labelRect = [cellText boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:cellFont} context:NSLineBreakByWordWrapping];
CGSize labelSize = labelRect.size;
return labelSize;
}
CGFloat width = CGRectGetWidth(self.tableView.frame) - 40.0f; -
Calculation of the maximum available width of the text, you can use self.view.frame or etc. - 40.0f - because i have indentation from the edge = 20.0f
Try this it working for me
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGSize labelSize = [[[Array objectAtIndex:indexPath.row] valueForKey:#"detail"] sizeWithFont:[UIFont boldSystemFontOfSize:10] constrainedToSize:CGSizeMake(255, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
return labelSize.height +15;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpletableidentifier=#"simpletableidentifier";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:simpletableidentifier];
if(cell == nil)
{
cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpletableidentifier];
CGSize labelSize = [[[Array objectAtIndex:indexPath.row] valueForKey:#"detail"] sizeWithFont:[UIFont boldSystemFontOfSize:10] constrainedToSize:CGSizeMake(255, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
UILabel *desc=[[UILabel alloc]initWithFrame:CGRectMake(35,2,245,labelSize.height)];
desc.backgroundColor=[UIColor clearColor];
desc.tag=2;
desc.numberOfLines=0;
desc.lineBreakMode=NSLineBreakByWordWrapping;
desc.font=[UIFont boldSystemFontOfSize:10];
desc.textColor=[UIColor whiteColor];
[cell.contentView addSubview:desc];
}
NSString *Str3 = [[Array objectAtIndex:indexPath.row] valueForKey:#"detail"];
UILabel *desc=(UILabel *)[cell.contentView viewWithTag:2];
desc.text=Str3;
cell.selectionStyle=UITableViewCellSelectionStyleNone;
cell.backgroundColor=[UIColor clearColor];
cell.contentView.backgroundColor=[UIColor clearColor];
return cell;
}
Finally figured it out. #RoryMcKinnel's comment does help. Here's what I did in case it can help others. The problem was that I had two type of cells, one where I need to adjust the height (additionalText) and one where I do not need to do that.
In the raw version, I override both estmatedHeightForRowAtIndexPath and heightForRowAtIndexPath and in both methods if the index is for row which is additionalText, I send UITableViewAutomaticDimension else I send the frame height. Of course refinements can be done :) to send better values, but the core concept is same.
here is the code.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.additionalTexts[#((long) indexPath.row)] != nil){
return UITableViewAutomaticDimension;
} else return [[SongTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainCellIdentifier].frame.size.height;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.additionalTexts[#((long) indexPath.row)] != nil){
return UITableViewAutomaticDimension;
} else return [[SongTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainCellIdentifier].frame.size.height;
}
and the resulting screen looks like
I'm experiencing some trouble with a UILabel in a UITableViewCell that extend its height nicely. But when the cell is reused, and the UILabel text changes, scrolling back up passed labels with correct height when I scrolled down, now is wrong.
As far as I can understand, this is an issue with the UILabel height, but I don't understand what and why it happens.
Heres a video of it happening:
You can see how the labels in the table cells below the images is looking good, but when I scroll back up, they are suddenly only two lines, instead of four.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
InstagramMedia *media = mediaArray[indexPath.section];
CGSize maximumLabelSize = CGSizeMake(304.0f, 20000.0f);
CGSize expectedLabelSize = [media.caption.text sizeWithFont:[UIFont systemFontOfSize:13.0f] constrainedToSize:maximumLabelSize lineBreakMode:NSLineBreakByWordWrapping];
return (320.0f + expectedLabelSize.height + 20.0f);
}
Am I missing something here?
I have tried using slightly different approach and it worked in the simulator. Cells kept their height on scrolling.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
InstagramMedia *media = mediaArray[indexPath.section];
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:#"HelveticaNeue" size:12], NSFonatAttributeName, nil];
NSAttributedString *textStr = [[NSAttrebutedString alloc]initWithString:media.caption.text attributes:attributes];
CGSize maximumLabelSize = CGSizeMake(304.0f, 20000.0f);
CGRect expLblRect = [textStr boundingRectWithSize:maximumLabelSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];
return (320.0f + expLblFrame.size.height + 20.0f);
}
Try this :
- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 186, 0)]; //max width that is allowed for label
lbl.numberOfLines = 0;
lbl.lineBreakMode = NSLineBreakByWordWrapping;
int GAP = 3;
float height = 0;
float fontSize = 14;
NSString *cellText = yourtext;
lbl.font= [ UIFont fontWithName:FONT_NAME_Ubuntu size: fontSize];
bl.text = cellText;
[lbl sizeToFit];
height += lbl.frame.size.height;
height += GAP;
return height;
}
Or you can try this :
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
for dynamic cell heigh according to the description display in cell
*/
NSDictionary *dict1 = (NSDictionary*)[array objectAtIndex:indexPath.row];
NSString *cellText = [dict1 valueForKey:#"test"];
UIFont *cellFont = [UIFont fontWithName:FONT_NAME_GOTHAM_4 size:11.0];
CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
return labelSize.height + 80;
}
The frame of the label in tableViewCell can not be set in the ableView:cellForRowAtIndexPath: method. In fact as show in the NSLog, the label's frame has changed but it did not show on the view. I expected the label(with green background) should be taller than in the picture, which can show all the text in it. The Prototype Cell with Identifier "cell" is created in the storyboard. Any help will be appreciated.
ps: Xcode 5.0.2, iOS7
- (void)viewDidLoad
{
[super viewDidLoad];
NSString * str = #"Do any additional setup after loading the view, typically from a nib Do any additional setup after loading the view, typically from a nib Do any additional setup after loading the view, typically from a nib";
NSArray *array = [NSArray arrayWithObjects:str, str, str , str, str, str, nil];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSInteger row = indexPath.row;
CGSize sizeConstraint = CGSizeMake(tableView.frame.size.width, 2000);
CGSize size = [[array objectAtIndex:row] boundingRectWithSize:sizeConstraint options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName: [UIFont fontWithName:FontName size:FontSize]} context:nil].size;
return size.height + 20;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSInteger row = indexPath.row;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UILabel *label = (UILabel *)[cell.contentView viewWithTag:1];
label.autoresizingMask = UIViewAutoresizingNone;
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.font = [UIFont fontWithName:FontName size:FontSize];
label.backgroundColor = [UIColor greenColor];
label.text = [array objectAtIndex:row];
CGSize sizeConstraint = CGSizeMake(tableView.frame.size.width, 2000);
CGSize size = [label.text boundingRectWithSize:sizeConstraint options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName: label.font} context:nil].size;
CGRect rect = label.frame;
rect.size.height = size.height;
[label setFrame:rect];
NSLog(#"label height :%f", label.frame.size.height);
[label sizeThatFits:sizeConstraint];
return cell;
}
when you scroll the tableView, you can see the label in the first and second cell are well displayed now. (Here i just scrolled out the two cells and pull them back.)
In your post I don't find the definition of labelBible that you use to set the frame of the label.
Using constraint it's quick:
and
In this way you don't have to do anything in your -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method.
Edit: to use constraint: Use Autolayout has to be checked.
Hope that will work as you want.
just uncheck the auto layout from the file inspector of the label frame.
I'm using tableview on storyboard.
I change label's frame in (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath function.
then, after some scrolling, it can change frame. but, when I open my application, frame doesn't change at first.
sorry, can't post image till 10 reputation.
please help.
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
// get one row
Plan* planObj = [_planObjList objectAtIndex:indexPath.row];
// get custom cell info
LargeImageCell* cell = (LargeImageCell*)[tableView dequeueReusableCellWithIdentifier:#"CustomLargeImageCell"];
cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"bg"]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.titleLabel.text = planObj.planTitle;
cell.titleLabel.numberOfLines = 0;
cell.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
cell.userNameLabel.text = planObj.getProducerName;
// title size
CGSize titleSize = [cell.titleLabel.text boundingRectWithSize:CGSizeMake(300.0f, CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin) attributes:#{NSFontAttributeName: cell.titleLabel.font} context:nil].size;
// user name size
CGSize userNameSize = [cell.userNameLabel.text boundingRectWithSize:CGSizeMake(300.0f, CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin) attributes:#{NSFontAttributeName: cell.userNameLabel.font} context:nil].size;
// set title size
cell.titleLabel.frame = CGRectMake(7.0f, 230.0f, 306.0f, ceilf(5.0f + titleSize.height));
cell.titleLabel.backgroundColor = [UIColor redColor];
// set name size
cell.userNameLabel.frame = CGRectMake(7.0f, ceilf(235.0f + titleSize.height), 148.0f, ceilf(5.0f + userNameSize.height));
cell.userNameLabel.backgroundColor = [UIColor blueColor];
}
autolayout was problem.
I switched off 'Use Autolayout' on storyboard. then, it became clear.
thank you all.
If your app is using Autolayout you should do it with Constraints. To resize a UILabel with Constraints that should has at least that properties:
Line Numbers = 0
Line Breaks = Word Wrap
And about Constraints you should set in both sides, and one to top, DONT set to bottom!!
To set right size in the row u can use this code example:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
id data = [self.listOfNews safeObjectAtIndex:indexPath.row];
UIFont *font = [UIFont fontWithName:K_FONT_AVENIR_MEDIUM size:textSize];
if ([data isKindOfClass:[NewsModel class]]) {
NewsModel *news = (NewsModel *)data;
if (SYSTEM_VERSION_LESS_THAN(#"7.0")) {
CGSize constraintSize = CGSizeMake(cellTextWidth, MAXFLOAT);
CGSize textRect = [news.title sizeWithFont:font constrainedToSize:constraintSize];
return textRect.height + paddingTopAndBottom;
} else {
CGRect textRect = [news.title boundingRectWithSize:CGSizeMake(cellTextWidth, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil];
return textRect.size.height + paddingTopAndBottom;
}
}
return 0;
}
Try resizing frames in willDisplayCell delegate method.
You can't change the size initially through cellForRow method. You need to calculate the size and return it in the following delegate
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
To calculate size for a label based on the text use
NSString *labelText=#"some text";
[myLabel setText:labelText];
UIFont *labelTextFont = [UIFont fontWithName:#"Helvetica" size:labelTextsize];
CGSize labelFrameSize = [labelText sizeWithFont:labelTextFont];
myLabel.frame = CGRectMake(xPos, yPos, labelFrameSize.width, labelFrameSize.height);
Remember these steps in order to have UILabel to change size:
1) If you have a Custom UITableViewCell, switch off AutoLayout on elements of the cell
2) Use heightForRowAtIndex protocol method to change the height
3) Set the numberOfLines = 0 for the UILabel inside the cell
4) If this does not work re-set the frame ( I found that this happens when you are trying to enlarge a UILabel in some "far" end of the cell)
Examples
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
GeneralCell* cell = [tableView dequeueReusableCellWithIdentifier:#"GeneralCell"];
if (cell == nil) {
cell = [[GeneralCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"GeneralCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
/////// USE the following block if still in trouble
CGRect frame = cell.label.frame;
[cell.label setFrame:frame];
[cell.label sizeToFit]; // this should not be necessary in general
///////////
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *detail = [NSString stringWithFormat:#"YOUR TEXT]];
CGSize constraintSize = CGSizeMake(CELL_CONTENT_WIDTH, MAXFLOAT);
CGSize labelSize = [detail boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont systemFontOfSize:FONT_SIZE]}
context:nil].size;
float h = (fmod((int)labelSize.height ,2) == 0) ? labelSize.height : labelSize.height+1;
CGFloat height = MAX(h, 30.0f);
elemento = nil;
detail = nil;
return height + (CELL_CONTENT_MARGIN * 2);
}
I am using a custom UITableViewCell which has some labels, buttons and image views to be displayed. There is one label in the cell whose text is a NSString object and the length of string could be variable. Due to this, I cannot set a constant height to the cell in the UITableView's heightForCellAtIndex method. The cell's height depends on the label's height which can be determined using the NSString's sizeWithFont method. I tried using it, but it looks like I'm going wrong somewhere. How can it be fixed?
Here is the code used for initializing the cell.
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier])
{
self.selectionStyle = UITableViewCellSelectionStyleNone;
UIImage *image = [UIImage imageNamed:#"dot.png"];
imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(45.0,10.0,10,10);
headingTxt = [[UILabel alloc] initWithFrame: CGRectMake(60.0,0.0,150.0,post_hdg_ht)];
[headingTxt setContentMode: UIViewContentModeCenter];
headingTxt.text = postData.user_f_name;
headingTxt.font = [UIFont boldSystemFontOfSize:13];
headingTxt.textAlignment = UITextAlignmentLeft;
headingTxt.textColor = [UIColor blackColor];
dateTxt = [[UILabel alloc] initWithFrame:CGRectMake(55.0,23.0,150.0,post_date_ht)];
dateTxt.text = postData.created_dtm;
dateTxt.font = [UIFont italicSystemFontOfSize:11];
dateTxt.textAlignment = UITextAlignmentLeft;
dateTxt.textColor = [UIColor grayColor];
NSString * text1 = postData.post_body;
NSLog(#"text length = %d",[text1 length]);
CGRect bounds = [UIScreen mainScreen].bounds;
CGFloat tableViewWidth;
CGFloat width = 0;
tableViewWidth = bounds.size.width/2;
width = tableViewWidth - 40; //fudge factor
//CGSize textSize = {width, 20000.0f}; //width and height of text area
CGSize textSize = {245.0, 20000.0f}; //width and height of text area
CGSize size1 = [text1 sizeWithFont:[UIFont systemFontOfSize:11.0f]
constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
CGFloat ht = MAX(size1.height, 28);
textView = [[UILabel alloc] initWithFrame:CGRectMake(55.0,42.0,245.0,ht)];
textView.text = postData.post_body;
textView.font = [UIFont systemFontOfSize:11];
textView.textAlignment = UITextAlignmentLeft;
textView.textColor = [UIColor blackColor];
textView.lineBreakMode = UILineBreakModeWordWrap;
textView.numberOfLines = 3;
textView.autoresizesSubviews = YES;
[self.contentView addSubview:imageView];
[self.contentView addSubview:textView];
[self.contentView addSubview:webView];
[self.contentView addSubview:dateTxt];
[self.contentView addSubview:headingTxt];
[self.contentView sizeToFit];
[imageView release];
[textView release];
[webView release];
[dateTxt release];
[headingTxt release];
}
This is the label whose height and width are going wrong:
textView = [[UILabel alloc] initWithFrame:CGRectMake(55.0,42.0,245.0,ht)];
Your UITableViewDelegate should implement tableView:heightForRowAtIndexPath:
Objective-C
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [indexPath row] * 20;
}
Swift 5
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return indexPath.row * 20
}
You will probably want to use NSString's sizeWithFont:constrainedToSize:lineBreakMode: method to calculate your row height rather than just performing some silly math on the indexPath :)
If all your rows are the same height, just set the rowHeight property of the UITableView rather than implementing the heightForRowAtIndexPath. Apple Docs:
There are performance implications to using tableView:heightForRowAtIndexPath: instead of rowHeight. Every time a table view is displayed, it calls tableView:heightForRowAtIndexPath: on the delegate for each of its rows, which can result in a significant performance problem with table views having a large number of rows (approximately 1000 or more).
in a custom UITableViewCell -controller add this
-(void)layoutSubviews {
CGRect newCellSubViewsFrame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
CGRect newCellViewFrame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
self.contentView.frame = self.contentView.bounds = self.backgroundView.frame = self.accessoryView.frame = newCellSubViewsFrame;
self.frame = newCellViewFrame;
[super layoutSubviews];
}
In the UITableView -controller add this
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [indexPath row] * 1.5; // your dynamic height...
}
#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 300.0f
#define CELL_CONTENT_MARGIN 10.0f
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
/// Here you can set also height according to your section and row
if(indexPath.section==0 && indexPath.row==0)
{
text=#"pass here your dynamic data";
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 44.0f);
return height + (CELL_CONTENT_MARGIN * 2);
}
else
{
return 44;
}
}
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
UILabel *label = nil;
cell = [tv dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"Cell"];
}
********Here you can set also height according to your section and row*********
if(indexPath.section==0 && indexPath.row==0)
{
label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setLineBreakMode:UILineBreakModeWordWrap];
[label setMinimumFontSize:FONT_SIZE];
[label setNumberOfLines:0];
label.backgroundColor=[UIColor clearColor];
[label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
[label setTag:1];
// NSString *text1 =[NSString stringWithFormat:#"%#",text];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
if (!label)
label = (UILabel*)[cell viewWithTag:1];
label.text=[NSString stringWithFormat:#"%#",text];
[label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
[cell.contentView addSubview:label];
}
return cell;
}
I saw a lot of solutions but all was wrong or uncomplet.
You can solve all problems with 5 lines in viewDidLoad and autolayout.
This for objetive C:
_tableView.delegate = self;
_tableView.dataSource = self;
self.tableView.estimatedRowHeight = 80;//the estimatedRowHeight but if is more this autoincremented with autolayout
self.tableView.rowHeight = UITableViewAutomaticDimension;
[self.tableView setNeedsLayout];
[self.tableView layoutIfNeeded];
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0) ;
For swift 2.0:
self.tableView.estimatedRowHeight = 80
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.setNeedsLayout()
self.tableView.layoutIfNeeded()
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0)
Now create your cell with xib or into tableview in your Storyboard
With this you no need implement nothing more or override. (Don forget number os lines 0) and the bottom label (constrain) downgrade "Content Hugging Priority -- Vertical to 250"
You can donwload the code in the next url:
https://github.com/jposes22/exampleTableCellCustomHeight
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
CGSize constraintSize = {245.0, 20000}
CGSize neededSize = [ yourText sizeWithFont:[UIfont systemFontOfSize:14.0f] constrainedToSize:constraintSize lineBreakMode:UILineBreakModeCharacterWrap]
if ( neededSize.height <= 18)
return 45
else return neededSize.height + 45
//18 is the size of your text with the requested font (systemFontOfSize 14). if you change fonts you have a different number to use
// 45 is what is required to have a nice cell as the neededSize.height is the "text"'s height only
//not the cell.
}
To set automatic dimension for row height & estimated row height, ensure following steps to make, auto dimension effective for cell/row height layout.
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.
Here in this example I set low hugging and high compression resistance priority, that leads to set more priority/importance for contents of second (yellow) label.
Thanks to all the posts on this topic, there are some really helpful ways to adjust the rowHeight of a UITableViewCell.
Here is a compilation of some of the concepts from everyone else that really helps when building for the iPhone and iPad. You can also access different sections and adjust them according to the varying sizes of views.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
int cellHeight = 0;
if ([indexPath section] == 0)
{
cellHeight = 16;
settingsTable.rowHeight = cellHeight;
}
else if ([indexPath section] == 1)
{
cellHeight = 20;
settingsTable.rowHeight = cellHeight;
}
return cellHeight;
}
else
{
int cellHeight = 0;
if ([indexPath section] == 0)
{
cellHeight = 24;
settingsTable.rowHeight = cellHeight;
}
else if ([indexPath section] == 1)
{
cellHeight = 40;
settingsTable.rowHeight = cellHeight;
}
return cellHeight;
}
return 0;
}
To have the dynamic cell height as the text of Label increases, you first need to calculate height,that the text gonna use in -heightForRowAtIndexPath delegate method and return it with the added heights of other lables,images (max height of text+height of other static componenets) and use same height in cell creation.
#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 300.0f
#define CELL_CONTENT_MARGIN 10.0f
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
if (indexPath.row == 2) { // the cell you want to be dynamic
NSString *text = dynamic text for your label;
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 44.0f);
return height + (CELL_CONTENT_MARGIN * 2);
}
else {
return 44; // return normal cell height
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UILabel *label;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] ;
}
label = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 280, 34)];
[label setNumberOfLines:2];
label.backgroundColor = [UIColor clearColor];
[label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
label.adjustsFontSizeToFitWidth = NO;
[[cell contentView] addSubview:label];
NSString *text = dynamic text fro your label;
[label setText:text];
if (indexPath.row == 2) {// the cell which needs to be dynamic
[label setNumberOfLines:0];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
[label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
}
return cell;
}