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.
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;
}
I am trying to add 2 labels in my table view cell.
when in portrait mode the both labels overlap each other and in landscape mode it works fine.
I have also used auto-layout . Where i have to make changes to achieve the target.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"ProductTableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
UILabel * productName= (UILabel *)[cell viewWithTag:101];
//productName.text=[[productDetails objectAtIndex:indexPath.row]product_Name];
// similar code for another label also
productName.lineBreakMode= NSLineBreakByWordWrapping;
productName.numberOfLines=0;
productName.text= #"asdfasdfsdzxcvzasdfaxv";
[productName sizeToFit];
return cell;
}
Link for Issue for better description : http://f.talk.to/3afcd0c13764064184c01cc4
Thanks in advance :)
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
I have 2 UILabels in a Prototype Cell designed in the Storyboard. Both have their designated tag number (1000 and 1001). When I write the tableView cellForRowAtIndexPath: method it seems that one of the labels is receiving the relevant NSString and the other one doesn't.
Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ContentCell";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
ContentObject * contentObject = [contentPackageManager.contentObjectsArray objectAtIndex:[indexPath row]];
//contentPackageManager is a class that holds an NSArray of ContentObjects (it does a few other things, but they are not relevant for this method...)
//ContentObject is a class that holds several attributs such as: NSString*name, NSString*type, etc...
UILabel *nameLabel = (UILabel *)[cell viewWithTag:1000];
nameLabel.text = contentObject.name; //this line works OK
UILabel * typeLabel = (UILabel *)[cell viewWithTag:1001];
typeLabel.text = contentObject.contentType; //this is the PROBLEMATIC one - no effect on the actual UILabel
return cell;
}
Is anyone familiar with this issue?
Am I doing something wrong?
Please check if contentObject.contentType is not null.
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