I'm having a problem with my iOS app and getting a UILabel in a UITableViewCell to wrap. The text shows but it will only display on one line.
Here is my code:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
UILabel *noteLabel = (UILabel *)[cell.contentView viewWithTag:2];
NSDictionary *contact = [jsonResults objectAtIndex:indexPath.row];
noteLabel.lineBreakMode = UILineBreakModeWordWrap;
noteLabel.numberOfLines = 0;
noteLabel.text = [contact objectForKey:#"note"];
return cell;
}
I believe the problem has something to do with this line:
UILabel *noteLabel = (UILabel *)[cell.contentView viewWithTag:2];
I'm not sure how else to get the label from a tag and I think this line won't let me change the labels properties.
You may need to set the label's height:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
UILabel *noteLabel = (UILabel *)[cell.contentView viewWithTag:2];
NSDictionary *contact = [jsonResults objectAtIndex:indexPath.row];
noteLabel.lineBreakMode = UILineBreakModeWordWrap;
noteLabel.numberOfLines = 0;
noteLabel.text = [contact objectForKey:#"note"];
//Note: adjust the proper width to be constrained to
CGSize size = [noteLabel.text sizeWithFont:noteLabel.font forWidth:150 lineBreakMode:noteLabel.lineBreakMode];
CGRect labelFrame = noteLabel.frame;
labelFrame.size = size;
noteLabel.frame = labelFrame;
return cell;
}
Time has moved on since 2012. In the current Xcode 5 world, height is automatically expanded for the multiple lines if numberOfLines is set to 0 in either code or in Interface Builder. One thing that can prevent the multiple lines from being displayed in this scenario is if there is an AutoLayout height constraint set, in Interface Builder or in code. In this scenario, it will look like a label that has been truncated, though in contrast to a truncated label it will not end with an ellipsis (...).
In order for AutoLayout to function as expected, you would not normally want to set a higher height to the UILabel, unless you knew that UILabel would always have multiple lines.
What made the difference for me was setting the label's preferredMaxLayoutWidth.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UILabel_Class/#//apple_ref/occ/instp/UILabel/preferredMaxLayoutWidth
Related
I really can't get my head around why this isn't working properly.
I have a TableViewController with dynamic prototypes. I put 4 labels in a prototype named "InfoCell", and gave them constraints.
If i run the app with the following cellForRowAtIndexPath:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"InfoCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
return cell;
}
what I get is this. Everything looks fine 'til now
I did this just to check that the labels were being displayed in the right place. The page is supposed to show 2 cells, so everything looks fine.
Now, the problems start when I try to get a reference to the labels in order to change the text. Even without actually changing the text, if my code looks like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"InfoCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:10];
UILabel *surnameLabel = (UILabel *)[cell viewWithTag:20];
UILabel *roleLabel = (UILabel *)[cell viewWithTag:30];
UILabel *spouseNameLabel = (UILabel *)[cell viewWithTag:40];
[cell addSubview:nameLabel];
[cell addSubview:surnameLabel];
[cell addSubview:roleLabel];
[cell addSubview:spouseNameLabel];
return cell;
}
I get this. Labels' positions went nuts
I tried, for example, to change the frame of each label programmatically,
nameLabel.frame = CGRectMake(15.0, 50.0, 120.0, 20.0)
but it just doesn't do anything, I suppose because auto-layout is enabled... but I'm too far into the project to disable auto-layout. Plus I've seen the use of viewWithTag as I wrote above working without the need to re-locate the labels programmatically, so it bugs me not to know what's really happening there!
Remember that when you have constraints added on any of the UI object, you can't change the frame of that object by changing its CGRect. In fact, you should change its constraint value.
Now the problem in your code is ,
[cell addSubview:nameLabel];
[cell addSubview:surnameLabel];
[cell addSubview:roleLabel];
[cell addSubview:spouseNameLabel];
above 4 lines. When you have added a UILabel in storyboard, why are you adding them again by using addSubview method ? Remove above 4 lines, and to set text on your UILabel , you already have a reference which you are accessing by using their tag values. So your method should looks like as below.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"InfoCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:10];
UILabel *surnameLabel = (UILabel *)[cell viewWithTag:20];
UILabel *roleLabel = (UILabel *)[cell viewWithTag:30];
UILabel *spouseNameLabel = (UILabel *)[cell viewWithTag:40];
nameLabel.text = #"";
surnameLabel.text = #"";
roleLabel.text = #"";
spouseNameLabel.text = #"";
return cell;
}
Im trying to implement dynamically sized tableView cells. The cells have a UILabel (among other things) that holds a variable amount of text. Before I customized the cell I was just using cell.textLabel.text to set the text and the cell resized fine and all the text was shown. I did not have to mess with the label at all. But now I have a custom UILabel inside my cell and the text is being cut off. Ive looked at a lot of answers on here but nothing seems to be working.
Here is my code:
//This method gets the size of the text that will be inside the cell/label. This works fine
-(CGFloat)getLabelHeightForText:(NSString *)text andWidth:(CGFloat)labelWidth
{
CGSize maximumSize = CGSizeMake(labelWidth, 10000);
UIFont *systemFont = [UIFont systemFontOfSize:15.0];
//provide appropriate font and font size
CGSize labelHeightSize = [text sizeWithFont:systemFont
constrainedToSize:maximumSize
lineBreakMode:NSLineBreakByWordWrapping];
return labelHeightSize.height;
}
//Dynamically changes the cell height. This works fine
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *reviewText = [[self.reviews objectAtIndex:indexPath.row] objectForKey:#"reviewText"];
CGFloat textHeight = [self getLabelHeightForText:reviewText andWidth:self.tableView.frame.size.width];
return (textHeight + 40);
}
//This is what doesnt seem to be working.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//Review label
NSString *reviewText = [[self.reviews objectAtIndex:indexPath.row] objectForKey:#"reviewText"];
UILabel *reviewLabel = (UILabel *)[cell viewWithTag:102];
CGFloat reviewLabelHeight = [self getLabelHeightForText:reviewText andWidth:reviewLabel.frame.size.width];
reviewLabel.frame = CGRectMake(reviewLabel.frame.origin.x, reviewLabel.frame.origin.y, reviewLabel.frame.size.width, reviewLabelHeight);
reviewLabel.text = reviewText;
reviewLabel.numberOfLines = 0;
reviewLabel.lineBreakMode = NSLineBreakByWordWrapping;
NSLog(#"Height: %f", reviewLabel.frame.size.height);
NSLog(#"Width: %f", reviewLabel.frame.size.width);
// cell.textLabel.text = [[self.reviews objectAtIndex:indexPath.row] objectForKey:#"reviewText"];
//
// cell.textLabel.numberOfLines = 0;
//
// cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
return cell;
}
As you can see, ive logged the height and width of the label. The width stays a constant 280 which is correct and the height changes dynamically depending the text. Everything looks as if it should be working fine. But sadly it doesnt. The cell resizes fine. The label (judging from the NSLogs) seems to resize fine, so why does my text get cut off?
Thanks
I have currently resolved this by adding some autolayout constraints to my prototype cell. Turning off autolayout also worked.
I have three UILabels in my custom UITableViewCell.
It might be that some UILabels will be empty (label.text == #"")
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"EventCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSString *key = [[keysArray objectAtIndex:indexPath.section] description];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:100];
namelabel.text = #"Label 1";
UILabel *locationLabel = (UILabel *)[cell viewWithTag:101];
location.text = #"Label 2";
UILabel *timeLabel = (UILabel *)[cell viewWithTag:102];
timeLabel.text = #"";
return cell;
}
How can I centre all non-empty UILabels vertically in the cell using auto-layout?
This is how it looks with three labels
How it looks when one of UILables is empty
And this is how I want it to look:
This is tricky to achieve, but a simple shortcut may be to have a single label instead, with three lines of text, constrained to fill the whole height of the cell. The label will then auto-center its contents vertically.
You'd have three string properties on the cell instead of three labels, and your setters would build the final string (using \n for new lines) and set the label's text.
If each line of text has different styling, no problem, as you can use attributed strings.
How can I scale UITableViewCells based on the amount of content in them? In my cells I use 3 labels which represent a forum. The labels are named "alias", "date", and "comments". The third label comments, can be any number of size. Therefore, my cells need to become dynamically depending on how big the "comments" label is. Below is my relevant code:
- (UITableViewCell *)tableView:(UITableView *)pTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ForumthreadCell";
UITableViewCell *cell = [pTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Feedback *item = [self.items objectAtIndex:indexPath.row];
UILabel *aliasLabel = (UILabel *)[cell viewWithTag:1];
UILabel *commentLabel = (UILabel *)[cell viewWithTag:2];
UILabel *dateLabel = (UILabel *)[cell viewWithTag:3];
[aliasLabel setText:item.alias];
[commentLabel setText:item.comment];
[dateLabel setText:[self.dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:(double)item.time]]];
commentLabel.numberOfLines = 0;
[commentLabel sizeToFit];
CGSize textHeight = [commentLabel.text sizeWithFont:commentLabel.font constrainedToSize:CGSizeMake(maxWidth, lineHeight * commentLabel.numberOfLines)lineBreakMode:UILineBreakModeWordWrap];
return cell;
}
As you can see, I set the height of the commentsLabel with textHeight. But what shall I do from now on? If I know the height of the label, how can I set the Cell's height depending on commentLabel's height?. Please give code-examples based on my code. I think I should use the following method but I am not sure how to do it:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
}
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;
}
I think this could solve the problem.
You could make the Label declarations in your implementation:
#implementation pTableView
{
UILabel *aliasLabel;
}
Then in the row height you could use default Height (44) + aliasLabel.Height
return 44 + aliasLabel.frame.size.height;
Then if you need to differentiate between the labels in your table
aliasLabel.tag = indexpath.row
How can I scale UITableViewCells based on the amount of content in them? In my cells I use 3 labels which represent a forum. The labels are named "alias", "date", and "comments". The third label comments, can be any number of rows. Therefore, my cells need to become dynamically depending on the amount of text(size) it is in the "comments" label. Below is my relevant code:
- (UITableViewCell *)tableView:(UITableView *)pTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ForumthreadCell";
UITableViewCell *cell = [pTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Feedback *item = [self.items objectAtIndex:indexPath.row];
UILabel *aliasLabel = (UILabel *)[cell viewWithTag:1];
UILabel *commentLabel = (UILabel *)[cell viewWithTag:2];
UILabel *dateLabel = (UILabel *)[cell viewWithTag:3];
[aliasLabel setText:item.alias];
[commentLabel setText:item.comment];
[dateLabel setText:[self.dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:(double)item.time]]];
commentLabel.numberOfLines = 0;
[commentLabel sizeToFit];
return cell;
}
In this method am I supposed to set the tableViewCell's height depending on commentLabel height.. The only problem is I am not sure how to do it?
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (????) {
return ????;
//return [indexPath row] + 50;
}
return ????;
}
I need help from someone that tries to take a look at my code and give examples how I can make this work. After all, its only 1 label.... I have already looked at several tutorials but not been able to make it work... Thanx for your time and help.
This is an old screen with some old code. This is more or less what the forum looks like now: http://tinypic.com/view.php?pic=16h7me9&s=6
What you need is a way to calculate the size of a text rendered with a specific font. Luckily, UIKit provides you with exactly this via the various sizeWithFont: methods in NSString UIKit Additions.