I need to be able to adjust the height of a single cell in my UITableView so that it fits the amount of text in its detail label.
I have played with the following but it hasn't work for me:
How do I wrap text in a UITableViewCell without a custom cell
Attempted code:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
}
and
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellText = @"Go get some text for your cell.";
UIFont *cellFont = [UIFont fontWithName:@"Helvetica" size:17.0];
CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
return labelSize.height + 20;
}
This hasn't worked, it shows the entire string on the cell, however the cell height isn't affected at all.
Its simple, just add this to your code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
It automatically count an height of row and than return a float... :-)
Hope this helps!
Hi Josh,
Using tableView:heightForRowAtIndexPath:
you can give the size of each row at run time. now your problem is how to get height from your string there are function in NSString class by this code your problem,
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *str = [dataSourceArray objectAtIndex:indexPath.row];
CGSize size = [str sizeWithFont:[UIFont fontWithName:@"Helvetica" size:17] constrainedToSize:CGSizeMake(280, 999) lineBreakMode:NSLineBreakByWordWrapping];
NSLog(@"%f",size.height);
return size.height + 10;
}
by below line you set your label`s num. of line to max. so set it in cellForRowAtIndexPath: method.
cell.textLabel.numberOfLines = 0;
if you use some custom cell then manage all label`s string with this and get sum of all that height then set the height of your cell.
Edit : iOS 8 onwards if you set proper autolayout constraints to label then you have to set only following delegate method to achieve this.
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
//minimum size of your cell, it should be single line of label if you are not clear min. then return UITableViewAutomaticDimension;
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
that`s it. no any calculation required. For more information check this tutorial.
s your table dataSource array from where you feed your table
s label.
sizeWithFont
has been deprecated
UITableViewAutomaticDimension
in both estimatedHeightForRowAtIndexPath
and heightForRowAtIndexPath
works for me when using Custom style. :)
In your CustomCell
: Remember to add the constraint top and bottom for your UILabel
For adjust UILabel height depend on text just change UILabel
line to 0 (see the answer here)
Then in your code, just only set 2 line
self.tableView.estimatedRowHeight = 80;
self.tableView.rowHeight = UITableViewAutomaticDimension;
https://i.stack.imgur.com/vxUt0.png
https://i.stack.imgur.com/ccZVL.png
=== Suggestion ===
IF your cell has some UILabels
and Images
(not like my example) then:
You should put all UILabels and Images to one GroupView (View)
Add the constraint top and bottom to supper view for this GroupView (like the UILabel in my image)
Adjust UILabel height like the my suggestion above
Adjust the GroupView height depend on the content (the content is all UILabels and Images)
Finally, change estimateRowHeight and tableView.rowHeight like the code above
Hope this help
UILabels
and Images
in a groupview (View
). after that, you can think the groupview like one UILabel
. config the constraint and modify code, like my instruction. i'm sure it will work
Based on the code you have provided, I think you are increasing only the cell height and not the cell.textLabel's height.
Ideally, you should set the frame size of cell.textLabel and the cell for you to see the full text in the cell.
A neat way to see whats wrong with a view in terms of size, is to color it different than the background (try setting cell.textLabel background to yellow) and see if the height is actually being set.
Here's how it should be
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
NSString *cellText = @"Go get some text for your cell.";
UIFont *cellFont = cell.textLabel.font;
CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
cell.textlabel.frame.size = labelSize;
cell.text = cellText;
}
Hope this helps!
update: This is quite an old answer, and many lines in this answer may be deprecated.
UILineBreakModeWordWrap
is deprecated in iOS 6.0, use NSLineBreakByWordWrapping
instead
For swift developers:
Custom cell: At first you can calculate the height of the text like below:
func calculateHeight(inString:String) -> CGFloat
{
let messageString = inString
let attributes : [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 15.0)]
let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)
let rect : CGRect = attributedString.boundingRect(with: CGSize(width: 222.0, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)
let requredSize:CGRect = rect
return requredSize.height
}
Set the width of your text label
Then call this function:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
heightOfRow = self.calculateHeight(inString: conversations[indexPath.row].description)
return (heightOfRow + 60.0)
}
For Basic cell:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
This function will not work for custom cells.
Hope it will work.
In tableView:heightForRowAtIndexPath:
you can take the text and use sizeWithFont:constrainedToSize:
in order to get the size of the text.
Then just return the height plus some extra spacing for buffer.
You can write a method globally to make it so it can be used throughout the app. You need to pass the text, font and width as per your requirement.
In Swift 4:
func heightForText(text: String,Font: UIFont,Width: CGFloat) -> CGFloat{
let constrainedSize = CGSize.init(width:Width, height: CGFloat(MAXFLOAT))
let attributesDictionary = NSDictionary.init(object: Font, forKey:NSAttributedStringKey.font as NSCopying)
let mutablestring = NSAttributedString.init(string: text, attributes: attributesDictionary as? [NSAttributedStringKey : Any])
var requiredHeight = mutablestring.boundingRect(with:constrainedSize, options: NSStringDrawingOptions.usesFontLeading.union(NSStringDrawingOptions.usesLineFragmentOrigin), context: nil)
if requiredHeight.size.width > Width {
requiredHeight = CGRect.init(x: 0, y: 0, width: Width, height: requiredHeight.height)
}
return requiredHeight.size.height;
}
I was able to get this accomplished using autolayout. Make sure your label snaps to the top and bottom of the cell (I'm using a prototype cell), and it's lines set to 0. Then in the tableView:heightForRowAtIndexPath:sizeWithFont:constrainedToSize:
you can set the height of the cell by doing the calculation on the text size:
NSString *key = self.detailContent.allKeys[indexPath.row];
NSDictionary *dictionary = self.detailContent[key];
NSString *cellText = dictionary[kSMDetailTableViewCellTextKey];
UIFont *cellFont = [UIFont fontWithName:kFontKeyEmondsans size:12.0];
CGSize constraintSize = CGSizeMake(252.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
return labelSize.height;// + 10;
tableView:heightForRowAtIndexPath:sizeWithFont:constrainedToSize:
from? tableView:heightForRowAtIndexPath:
is in UITableViewDelegate
, but the sizeWithFont part doesn't sound like it's from an Apple UITableView protocol. sizeWithFont
from the UIKit category on NSString was deprecated in iOS 7 if that's what this is referring to.
NSString *str;
NSArray* dictArr;
if (_index==0) {
dictArr = mustangCarDetailDictArr[indexPath.section];
}
NSDictionary* dict = dictArr[indexPath.row];
if (indexPath.section ==0)
{
str = [dict valueForKey:@"FeatureName"];
if ([[dict valueForKey:@"FeatureDetail"] isKindOfClass:[NSString class]])
{
str = [dict valueForKey:@"FeatureDetail"];
}
else
{
if (dictArr.count>indexPath.row+1)
{
NSDictionary* dict2 = dictArr[indexPath.row+1];
if ([[dict2 valueForKey:@"FeatureDetail"] isKindOfClass:[NSString class]])
{
}
}
}
}
CGSize size = [str sizeWithFont:[UIFont fontWithName:@"Helvetica" size:17] constrainedToSize:CGSizeMake(280, 999) lineBreakMode:NSLineBreakByWordWrapping];
NSLog(@"%f",size.height);
return size.height + 20;
}