UILabel doesn't change height on setFrame - iphone

I'm trying to change the height of a UILabel depending on how much text is in the label.
I can calculate the size required for the label but when I try to set the UILabel frame it just doesn't change.
Below is my code.
Even if I replace size.height in the last line to something like 500 the size of the UILabel frame doesn't change
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"GameItemCell";
GameItemCell *cell = (GameItemCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"GameItemCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
GameItem* item = [_hunt.gameItems objectAtIndex: indexPath.row];
cell.itemHeaderLabel.text = [NSString stringWithFormat:#"#%d - (%d pts)", indexPath.row+1, item.itemPoints];
UILabel* textLabel = cell.itemTextLabel;
textLabel.text = item.itemText;
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGRect frame = cell.itemTextLabel.frame;
CGSize textSize = { frame.size.width, 20000.0f };
CGSize sizeOneLine = [#"one line" sizeWithFont:cell.itemTextLabel.font constrainedToSize:textSize lineBreakMode:NSLineBreakByWordWrapping];
CGSize cellTextSize = [item.itemText sizeWithFont:cell.itemTextLabel.font constrainedToSize:textSize lineBreakMode:NSLineBreakByWordWrapping];
CGSize sizeOneLineSpacing = CGSizeMake(sizeOneLine.width, sizeOneLine.height + 3);
NSInteger lines = cellTextSize.height / sizeOneLine.height;
CGSize size = CGSizeMake(frame.size.width, lines * sizeOneLineSpacing.height);
textLabel.frame = CGRectMake(frame.origin.x, frame.origin.y, size.width, size.height);
return cell;
}

You must set the frame of your label in GameItemCell inside -(void)layoutSubviews

Instead of doing all that hard work, try it like:
textLabel.numberOfLines = 0;
textLabel.text = textString;
[textLabel sizeToFit];
remember sizeToFit respect your labels default width, so set width according to your requirement. And then Height will be managed by the sizeToFit method.

In the end you will need to put something like these two methods in your UITableViewCell subclass:
// call this method on your cell, during cellForRowAtIndexPath
// provide your resizing info (frame, height, whatever)
- (void) updateLabelFrame:(CGRect)newLabelFrame {
self.resizedLabelFrame = newLabelFrame;
[self setNeedsLayout];
}
// the actual resize happens here when UIKit gets around to it
- (void) layoutSubviews {
[super layoutSubviews];
self.myLabel.frame = self.resizedLabelFrame;
}

You have missed numberOfLines property to set.
Add :
textLabel.numberOfLines = 0;

CGRect labelFrame = myLabel.frame;
labelFrame.size = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:CGSizeMake(myLabel.frame.size.width, CGFLOAT_MAX)
lineBreakMode:myLabel.lineBreakMode];
cell.textLabel.frame = labelFrame;

numberOfLines
The maximum number of lines to use for rendering text.
The default value for this property is 1. To remove any maximum limit, and use as many lines as needed, set the value of this property to 0.
tack a look UILabel Class Reference
According to your question you can set no of lines
Now number of lines is not set to your label, so set it,
textLabel.numberOfLines = lines;

Yeah, for multiple lines use textLabel.numberOfLines = 0; in cellForRowAtIndexPath
But Still you need to change the height of the cell too:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Calculate new cell height too as you are doing in cellForRowAtIndexPath
return YOUR_SIZE;;
}

Try this :
NSString *text1 = shareObjC.commentText;
CGSize constraint1 = CGSizeMake(280 - (size.width + 5), 2000);
CGSize size1 = [text1 sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:constraint1 lineBreakMode:UILineBreakModeWordWrap];
UILabel *lblComment = [[[UILabel alloc] initWithFrame:CGRectMake(posx,posy,size1.width,size1.height)] autorelease];
lblComment.lineBreakMode = UILineBreakModeWordWrap;
lblComment.numberOfLines = size1.height/15;
[lblComment setFont:[UIFont systemFontOfSize:12]];
lblComment.text = text1;
[cell.viewLikeComment addSubview:lblComment];

Related

UILabel in a grouped table view's header doesn't wrap text

I have a label whose text is longer that the table view's header containing it, so I want the label to be split into N lines according to the width available. This is my code:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 1) {
UIView *wrapper = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)];
[wrapper setBackgroundColor:[UIColor clearColor]];
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)];
textLabel.text = NSLocalizedString(#"This is supposed to be a very long text that may fill several lines", #"");
[textLabel setLineBreakMode:UILineBreakModeWordWrap];
[textLabel setNumberOfLines:0];
[wrapper addSubview:textLabel];
return wrapper;
}
else
return nil;
}
However, the label is in a single line and I can't see the end of the text. What am I missing?
Thanks!
You should implement the delegate method heightForHeaderInSection.
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if(section ==1)
return 100;
else
return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 1) {
NSString *text = NSLocalizedString(#"This is supposed to be a very long text that may fill several lines", #"");;
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:10] constrainedToSize:CGSizeMake(self.tableView.frame.size.width, 999) lineBreakMode:NSLineBreakByWordWrapping];
CGRect frame = CGRectZero;
frame.size = size;
UIView *wrapper = [[UIView alloc] initWithFrame:frame];
[wrapper setBackgroundColor:[UIColor clearColor]];
UILabel *textLabel = [[UILabel alloc] initWithFrame:frame];
textLabel.text = NSLocalizedString(#"This is supposed to be a very long text that may fill several lines", #"");
[textLabel setLineBreakMode:UILineBreakModeWordWrap];
[textLabel setNumberOfLines:0];
[wrapper addSubview:textLabel];
return wrapper;
}
else
return nil;
}
use this if you want to support iOS below 6.0
textLabel.lineBreakMode = UILineBreakModeWordWrap;
textLabel.numberOfLines = 0;
As UILineBreakModeWordWrap deprecated now.
otherwise use this
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;
you should set size of label as text in heightForRowAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *text;
CGSize textViewSize;
int width = 270;
textViewSize = [text sizeWithFont:[UIFont fontWithName:#"Helvetica Neue" size:14.0]
constrainedToSize:CGSizeMake(width, FLT_MAX)
lineBreakMode:UILineBreakModeCharacterWrap];
CGFloat height = MAX(textViewSize.height, 44.0f);
return height;
}
and in cellForRowAtIndexPath write this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
textViewSize = [text sizeWithFont:[UIFont fontWithName:#"Helvetica Neue" size:14.0]
constrainedToSize:CGSizeMake(width, FLT_MAX)
lineBreakMode:UILineBreakModeCharacterWrap];
// / CGFloat height = MAX(textViewSize.height, 44.0f);
// if (!lblParameter){
// lblParameter = (UILabel*)[cell viewWithTag:1];}
CGFloat height = MAX(textViewSize.height, 44.0f);
[lblParameter setText:text];
[lblParameter setFont:[UIFont fontWithName:#"Helvetica Neue" size:14.0]];
[lblParameter setFrame:CGRectMake(10, 0,width,height)];
[[cell contentView] addSubview:lblParameter];
}
you need caculate the height of uilabel this height equal font size * numberline
It seems that wrapping / formatting will not work on a label inside the header view - presumably because it's inheriting defaults from somewhere. So, a simple solution, which AFAIK breaks no laws, is to put the label inside a view inside the header view.
Using the storyboard, drag a view to the table view controller (above your prototype cell).
Add a second view to this view.
Add the label to this second view. Make sure both views and label are tall enough to allow for multiple lines of text. In the label's attributes, set Lines to 0 and Line Breaks to Word Wrap.
Wrapping will now work as expected.

Dynamically change UITable cell height?

I need to resize the cell height based on the content size/length.tried several methods, which one gives the exact height without overlapping?
see this tutorial for change UITableViewCell Height Dynamically..
Resizing-A-UITableViewCell
and also use this tutorial..
uitableviewcell-dynamic-height
also use tableView:heightForRowAtIndexPath: method for set height of cell with indexpath
This is from my previous answer - Customizing UITableViewCell's height:
Use this method to get the text height of the text
-(CGFloat)getLabelHeightForText:(NSString *)text andWidth:(CGFloat)labelWidth
{
CGSize maximumSize = CGSizeMake(labelWidth, 10000);
//provide appropriate font and font size
CGSize labelHeighSize = [text sizeWithFont: [UIFont fontWithName:#"Trebuchet MS" size:13.0f]
constrainedToSize:maximumSize
lineBreakMode:UILineBreakModeTailTruncation];
return labelHeighSize.height;
}
This method will return the height of the text you are passing. Add this method in your class. And use the tableView:heightForRowAtIndexPath: delegate method to set the height for each cell
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
Feedback *item = [self.items objectAtIndex:indexPath.row];
CGFloat textHeight = [self getLabelHeightForText:item.comment andWidth:162];//give your label width here
return textHeight;
}
Sample you can edit and try
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *itemAtIndex = (NSDictionary *)[chatQuestions objectAtIndex:indexPath.row];
if ([self sizeForText:[itemAtIndex objectForKey:#"text"]].height+20>50) {
return [self sizeForText:[itemAtIndex objectForKey:#"text"]].height+20;
}
else{
return 50;}
}
-(CGSize)sizeForText:(NSString*)text
{
CGSize constraintSize;
constraintSize.width = 190.0f;
constraintSize.height = MAXFLOAT;
UIFont *labelFont = [UIFont fontWithName:#"Noteworthy-Light" size:18];
CGSize stringSize =[text sizeWithFont:labelFont constrainedToSize: constraintSize lineBreakMode: UILineBreakModeWordWrap];
return stringSize;
}
//Calculate the expected size based on the font and linebreak mode of your label
CGSize maximumLabelSize = CGSizeMake(296,9999);
CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font constrainedToSize:maximumLabelSize lineBreakMode:yourLabel.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;
In your case you need to set the height of cell based on the label.
Check the link :
http://dcraziee.wordpress.com/2013/05/22/calculate-size-of-uillabel-base-on-text-in/
There is a function named
-(CGFloat)getHeightForLabel:(NSString *)_str font:(UIFont *)fontOfObject
Use that function to calculate height as :
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat _height = [self getHeightForLabel:self.label.text font:[self.label font]];
return _height;
}

Label in UITableViewCell subclass changes position

I have made a prototype cell in Interface Builder. This prototype contains an imageview which should change size depending on the length of a string.
Therefore I have written a method in my subclass of UITableViewCell to calculate the width of the text string with a given font and set this width to the width of the imageview.
This works fine until I push to another view controller and then go back to my table view. Then the view has been repositioned about 20 pixels to the right.
Does anyone know why this happens? This even happens if I set the x-position to something static, e.g. 200.
Update 1:
In my - (UITableViewCell *)tableView:cellForRowAtIndexPath: I use my subclass of UITableViewCell, DFolderCell. This calls the method - (void)updateIndicatorsCount:andStarred which sets the value of the count and the starred label and makes those labels and the images countIcon and starredIcon the width to the width of _count and _starred with a given font.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"folderCell";
DFolderCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[DFolderCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
int index = indexPath.row;
Folder *folder = (Folder *) [folders objectAtIndex:index];
FolderIcon icon = (FolderIcon) folder.icon.intValue;
cell.name.text = folder.name;
cell.icon.image = [[DFolders sharedFolders] imageForFolderIcon:icon];
int count = [[DDrafts sharedDrafts] amountOfDraftsInFolder:folder withType:DraftLoadTypeRecent];
int starred = [[DDrafts sharedDrafts] amountOfDraftsInFolder:folder withType:DraftLoadTypeStarred];
[cell updateIndicatorsCount:count andStarred:starred];
return cell;
}
The method below is part of my subclass DFolderCell
/* Update size of count and starred indicators */
- (void)updateIndicatorsCount:(int)_count andStarred:(int)_starred
{
UIFont *badgeFont = [UIFont systemFontOfSize:11.0];
UIImage *background;
_count = 1000; // Test
if (_count > 0)
{
self.count.text = [NSString stringWithFormat:#"%i", _count];
CGSize size = [self.count.text sizeWithFont:badgeFont];
CGRect frame = self.countIcon.frame;
frame.size.width = size.width;
frame.origin.x = 320 - 20 - size.width;
self.countIcon.frame = frame;
self.count.frame = frame;
background = [UIImage imageNamed:#"Folders_Badge_Count.png"];
self.countIcon.image = [background stretchableImageWithLeftCapWidth:2 topCapHeight:2];
self.count.hidden = NO;
self.countIcon.hidden = NO;
}
/* Code for _starred is similar to code for _count */
}
This is the result.
This is how it should always look (and how it looks before selecting a cell)
When a cell has been selected, a new viewcontroller has been pushed onto the navigation stack and I have popped this view controller by going back, this is how it looks.
Update 2:
I have kept the imageview in the cell prototype but commented out the code setting its size and its image to a stretchable image. I have also changed the background color of the label to a solid red to see the exact size of the label. The size seems to be correct.
This is my - (void)updateIndicatorsCount:andStarred: method now.
- (void)updateIndicatorsCount:(int)_count andStarred:(int)_starred
{
UIFont *badgeFont = [UIFont systemFontOfSize:11.0];
// UIImage *background;
_count = 1000;
if (_count > 0)
{
self.count.text = [NSString stringWithFormat:#"%i", _count];
CGSize size = [self.count.text sizeWithFont:badgeFont];
CGRect frame = self.countIcon.frame;
frame.size.width = size.width;
frame.origin.x = 320 - 30 - size.width;
self.count.frame = frame;
self.count.hidden = NO;
self.count.backgroundColor = [UIColor redColor];
/* DON'T DO ANYTHING TO THE IMAGE */
/*
background = [UIImage imageNamed:#"Folders_Badge_Count.png"];
self.countIcon.hidden = NO;
self.countIcon.image = [background stretchableImageWithLeftCapWidth:2 topCapHeight:2];
self.countIcon.frame = frame;
*/
}
}
Before pushing to another view controller:
After going back from the view controller:
Use this code in your cellForRowatindexpath it will solve your issue
[[[cell contentView] subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];

UITableViewCell dynamic height with label

I have created a UITableViewCell with a NIB file.
There is 1 label in it which is going to contain a tweet. So it needs to be a dynamic height. There also is a timeAgo label that has to fit underneath the tweet label.
I'm trying stuff with frames en sizes but I can't get the perfect solution..
I do this in the UITableViewCell file in the drawrect method.
self.tweet.lineBreakMode = UILineBreakModeWordWrap;
self.tweet.numberOfLines = 0;
self.tweet.font = [UIFont fontWithName:#"Arial" size:13.0f];
[self.tweet sizeToFit];
CGFloat tweetHeight = self.tweet.frame.size.height;
self.timeAgo.lineBreakMode = UILineBreakModeWordWrap;
self.timeAgo.numberOfLines = 0;
self.timeAgo.font = [UIFont fontWithName:#"Arial" size:11.0f];
[self.timeAgo sizeToFit];
CGFloat timeAgoHeight = self.timeAgo.frame.size.height;
self.timeAgo.frame = CGRectMake(88, tweetHeight, 100, timeAgoHeight + 10.0f);
I have also tried a stringhelper which I found in a tutorial.
The:
- (CGFloat)RAD_textHeightForSystemFontOfSize:(CGFloat)size {
My HeightForRow methods is also already different because I use different cell styles.
At the moment I return a hard value for each cell style but that also needs to change to the cellheight.
See this tutorial, http://www.cimgf.com/2009/09/23/uitableviewcell-dynamic-height/
The trick is to make the label grow with the size of the cell, than you can just set the size of the cell and the cell will grow with it.
Set the timeAgo label to align it self to the bottom of the cell.
Set the numberOfLines of tweet to 0 via IB,re move all the draw code and only implement the following:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
id item = [self.item objectAtIndex:indexpath.row];
CGFloat height = 85.0f;
if ([item isKindOfClass:[Tweet class]]) {
Tweet *tweet = (Tweet *)item;
CGSize titleSize = [tweet.tweet sizeWithFont:[UIFont fontWithName:#"Arial" size:13.0f] constrainedToSize:CGSizeMake(260.0f, MAXFLOAT)];
// adde the 24 pixels to get the height plus the time ago label.
height = titleSize.height + 24.0f;
} else if( [item isKinfOfClass:[SC_Release class]]) {
height = 65.0f;
}
return height;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *string = [tweetsArray indexPath.row];
CGSize labelSize = [string sizeWithFont:[UIFont fontWithName:#"Verdana" size:17.0]
constrainedToSize:CGSizeMake(280.0f, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
return labelSize.height + 20;
}

UITableView custom cell showing weird results?

UITableView custom cell showing weird results? I have my code below. Everything was showing fine until I put enough data to go off the initial screen then it started going crazy? My custom cell is shown below.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"customCell"; // This is identifier given in IB jason set this.
PostTableCustomCellController *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSLog(#"Cell created");
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"PostTableCustomCellController" owner:nil options:nil];
for(id currentObject in nibObjects)
{
if([currentObject isKindOfClass:[PostTableCustomCellController class]])
{
cell = (PostTableCustomCellController *)currentObject;
}
}
}
Post *post = [postsArray objectAtIndex:indexPath.row];
cell.authorName.text = post.author;
cell.deadline.text = post.deadline;
cell.description.text = post.description;
Post *myPost = [postsArray objectAtIndex:[indexPath row]];
NSString *text = myPost.description;
// Configure the cell...
// [[cell authorName] setText:#"1 day"];
// [[cell distance] setText:#"Austin, TX"];
// [[cell description] setText:#"dd" ];
// Might can remove these
UILabel *locationLabel = (UILabel *) [cell distance];
UILabel *postTextView = (UILabel *) [cell description];
//CGSize maximumLabelSize = CGSizeMake(254,88.0f);
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 88.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 35.0f);
CGFloat realHeight = height + 36.0f - (10);
CGSize expectedLabelSize = [text sizeWithFont:postTextView.font
constrainedToSize:constraint
lineBreakMode:postTextView.lineBreakMode];
CGRect newFrame = postTextView.frame;
newFrame.size.height = expectedLabelSize.height;
postTextView.frame = newFrame;
[[cell description] sizeToFit];
CGRect locationRect = locationLabel.frame; // calls the getter
locationRect.origin.y = realHeight;
/* CGFloat locRectHeight = postTextView.bounds.size.height; */
/* locationRect.origin.y = cell.bounds.size.height; */
locationLabel.frame = locationRect;
//[[cell authorName] setText:#"jgervin"];
[[cell viewForBackground] sizeToFit];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
Post *myPost = [postsArray objectAtIndex:[indexPath row]];
NSString *text = myPost.description;
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 88.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 35.0f);
return height + (CELL_CONTENT_MARGIN * 2) + 36.0f;
}
You queing up old cells as they go off screen do to your dequeReusableCell, and the content and properties from the old cell must still be there. When you add content to a cell make sure to clear any previous properties so you can avoid these issues, or just turn off dequeReusableCell.
It looks like a cell-reuse problem. Why dont your turn off the dequeue-cell mechanism and see if the problem goes away. If it does, take a look at the code in your custom cell - are you creating multiple copies of the field labels? It looks that way.