Dynamic Height UILabel works after moving offscreen - ios

I am trying to create multi-line dynamic UILabels in UITableViewCells. I have a custom UITableViewCell that has a 'comment' label. The cell and the label are created in storyboard.
I can compute the heights of the UITableViewCells properly based on the multi-line data to be stored in the UILabel (using heightForRowAtIndexPath). However, my problem lies in the actual UILabel content. The UILabel content will display only 1 line of data on table load. However, once a cell containing multiline UILabel data moves offscreen and comes back on screen, the multi-line data appears properly in the UILabel with multiple lines. Is there any way to fix this so that the multi-line data appears properly on table load?
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cCell = (CustomCell *)cell;
MyObject = [myArray objectAtIndex:indexPath.row];
cCell.commentLabel.frame = CGRectMake(65.0f, 28.0f, 243.0f, 200.0f);
cCell.commentLabel.text = MyObject.multi_line_text_data;
cCell.commentLabel.adjustsFontSizeToFitWidth = NO;
cCell.commentLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
cCell.commentLabel.font = [UIFont systemFontOfSize:13.0];
cCell.commentLabel.lineBreakMode = NSLineBreakByWordWrapping;
cCell.commentLabel.numberOfLines = 0;
[cCell.commentLabel sizeToFit];
}
Thanks!

Since you're doing this in the storyboard, you can set the necessary label properties there (lineBreakMode and number of lines). Just give the label a specific width constraint and constraints to the top, bottom, and left sides of the cell. Then, in code use sizeWithFont:constrainedToSize:lineBreakMode: in heightForRowAtIndexPath: to calculate the appropriate height for the cell based on the content of the label -- the label, because of its constraints, will expand along with the cell to the proper size. Something like this:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGSize rowSize = [self.theData[indexPath.row] sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(260, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
return rowSize.height + 30;
}
Here, 260 was the width I gave my label in IB, and the 30 is a fudge factor (determined empirically) to account for padding above and below the label.

I met the same problems. Unchecking Autolayout can fix it.

Related

Dynamic UIlabel inside UITableViewCell

The user can make a comment which can be can be any size or height. The comment label's dynamic content should fit into the cell.
I have allocated my label inside UITableViewCell with a key value.
cell.CommentLabel.text=[ResDiction objectForKey:#"Comment"];
cell.TimeLabel.text=[ResDiction objectForKey:#"CreateDate"];
cell.UserName.text=[ResDiction objectForKey:#"CreateUserName"];
cell.UserName.adjustsFontSizeToFitWidth=YES;
cell.CommentLabel.adjustsFontSizeToFitWidth=YES;
cell.CommentLabel.numberOfLines = 8;
cell.TimeLabel.adjustsFontSizeToFitWidth=YES;
How do I let the label's content determine the cell height?
You have to use
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableviwCell* cell=[tableview cellForRowAtIndexPath:indexPath];
cell.CommentLabel.text=[ResDiction objectForKey:#"Comment"];
cell.TimeLabel.text=[ResDiction objectForKey:#"CreateDate"];
cell.UserName.text=[ResDiction objectForKey:#"CreateUserName"];
cell.UserName.adjustsFontSizeToFitWidth=YES;
cell.CommentLabel.adjustsFontSizeToFitWidth=YES;
cell.CommentLabel.numberOfLines = 8;
cell.TimeLabel.adjustsFontSizeToFitWidth=YES;
float height= cell.cell.CommentLabel.frame.size.height+TimeLabel.frame.size.height+(all your UIFields you have used)
return height;
}
This method is will return the height for the cell while it is being created.
The code inside will do calculate height of each uiField and combine them, this will work if you are arranging like stacks in UITableview cell, or you have to modify the code inside the function as per you arrangement.

UILabel Height is not updating in UITableView at launch

I am trying to set height of UILabel dynamically in the UITableView. During the launch height update is not reflected but as soon as I scroll down and scroll up back, update can be seen.
At Launch
After Scroll down and Scrolling back up again - This what I need. See the change in text in front of player icon. I need the complete text at launch itself.
Here is the code that I am trying to use:
- (void) updateMessageTextForRow:(long)row ofCell:(ESGameStreamCellView *)cell
{
NSString *item = _gameFeedItems[row];
NSString *title = item ?: NSLocalizedString(#"[No Title]", nil);
cell.message.preferredMaxLayoutWidth = cell.message.bounds.size.width;
// Update message label height
CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);
CGSize expectedLabelSize = [title sizeWithFont:cell.message.font
constrainedToSize:maximumLabelSize
lineBreakMode:cell.message.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = cell.message.frame;
newFrame.size.height = expectedLabelSize.height;
cell.message.frame = newFrame;
NSLog(#"Message = %#, Height: %f", title, cell.message.frame.size.height);
}
During Custom TableCellView Initialization
- (void)awakeFromNib {
// Initialization code
self.backgroundColor = [UIColor clearColor];
_message.lineBreakMode = NSLineBreakByWordWrapping;
_message.numberOfLines = 0;
}
Code for the row height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// Currently fixed height. Will be calculating dynamic height after adjusting the views.
return 300;
}
Are you using autoLayout ? I highly suspect that your constraints aren't set up properly: the UIImageView top should by tied with the titleLabel's bottom.
Also, you should use the new property for dynamic row : rowHeight and estimatedRowHeight.
You are getting the correct height after the cell's reuse : set the preferredMaxLayoutWidth property in the viewDidLayoutSubviews inside your custom cell class.
firstly, you should understand of the working flow of tableview delegate in objective c. Your cell height & position will be fixed after init. that's why you have to define each row's height in
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// Currently fixed height. Will be calculating dynamic height after adjusting the views.
return 300;
}
From this point forward, your cell's height will be fixed, even if you re-config the frame.
The best practice is some article called "Dynamic height tableview cell" and you can easily find it here
http://www.raywenderlich.com/87975/dynamic-table-view-cell-height-ios-8-swift
I learn on above article (thanks for Joshua Greene) and re-write it to another library allow you to make a dynamic tableview easily. You can find it here
https://github.com/EugeneNguyen/XBMobile
it's not too perfect, but hope that if can help.

UITableViewCell fit textLabel to entire frame

I'm trying to get my UITableViewCell.textLabel property to autofit text both vertically and horizontally.
Right now my tableView is not scrollable, so the cell frame is not dynamic. I need the textLabel property to word wrap and resize to a set # of lines. Setting the numberOfLines to 0 isn't working because it cut off because my cell height is smaller than the textLabel final height. Using an arbitrary number for numberOfLines cuts off the text.
How can I resize my textLabel to fit within the frame of the cell?
Code below
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* cell = (UITableViewCell*)[tableView #"mycell"];
cell.textLabel.text = #"LOTS OF TEXT";
cell.textLabel.textAlignment = NSTextAlignmentCenter;
[cell.textLabel textRectForBounds:cell.bounds limitedToNumberOfLines:0];
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
cell.textLabel.numberOfLines = 0;
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.minimumScaleFactor = .5;
}
EDIT: If the cells are a set height this is straightforward. You will have to set a custom cell and textLabel in it, as I don't think you can't modify the textLabel in the basic or other preset cells the way you need to. Just add a text label and set constraints linking it to the four sides, with the minimum amount (can be zero). Labels automatically center text vertically if there is extra space, so making the label too tall shouldn't be a problem.
Original answer:
If you're not using tableView self-sizing cells, maybe to support iOS 7, then it won't matter what you do in the cell because the issue is in the tableView row heights. If a single label the classic boundingRect method will work. in tableView:heightForRowAtIndexpath: do
NSString *stringFromDataSource = #"Text For Label";
CGSize potentialSize = CGSizeMake(CGRectGetWidth(self.tableview.frame), CGFLOAT_MAX);
NSStringDrawingOptions optionsForMultiline = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
NSDictionary *attributes = #{
NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleBody]
}; //or whatever
CGRect rectForText = [stringFromDataSource boundingRectWithSize:potentialSize
options:optionsForMultiline
attributes:attributes
context:nil];
return CGRectGetHeight(rectForText);
Note that in your question, your various options for sizing the cell aren't going to be used if the textLabel is expanding with autolayout, unless there is a constraint capping the maximum size, at which point minimumScaleFactor and so on will kick in.

Issue with UITableViewCell and Autolayout

I'm trying to create a custom cell with 4 UILabels and a UITextView. I've laid out the elements. The UITextView is not scrollable. The problem I face it placing the last UILabel under the UITextView. I've tried pinning both(either) to the superview and nothing seems to work. It is always under the UITextView no matter what as shown below:
What more should I do to move the UILabel below the UITextView?
This the only change I've made in my code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
QXTInboxCell *inboxCell = (QXTInboxCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath];
CGFloat width = self.tableView.frame.size.width - inboxCell.question.frame.origin.x - QUESTION_RIGHT_MARGIN;
CGSize size = [inboxCell.question sizeThatFits:CGSizeMake(width, 400)];
[inboxCell.question sizeThatFits:size];
return (inboxCell.question.frame.origin.y + size.height + 20);
}
Please help. I'm on XCode 5.0.2. Thanks.
Add the following constraints:
TextView to superview (top space)
TextView to label (bottom/top space)
label to superview (bottom space)
then (AFTER you set the text of the textView) call
[cell setNeedsLayout]
Of course this only works if you calculated the correct height for the cell in heightForRowAtIndexPath:.

Setting UITextView height based on contentSize inside a UITableViewCell only works after the initial table load

I have a UITextView inside a UITableViewCell. I am attempting to set the height of the UITextView it based on the content size. Inside my cellForRowAtIndexPath method I have:
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
....
cell.text.text = textString; // cell.text is the UITextView
CGRect frame = cell.text.frame;
frame.size.height = cell.text.contentSize.height;
cell.text.frame = frame;
return cell;
There are other objects on the custom cell, but nothing has constraints. The interesting thing is that when the table view is first loaded, the UITextView does not resize. However, when another cell is loaded by scrolling down or back up, the UITextView resizes to the correct height based on the above code. Why isn't the initial table loading correctly.
The UITextView has a default width and height size. Let me know if I can add more details. I am not implementing heightForRowAtIndexPath, but the testing I am doing has not exceeded the default cell heights so this should not matter anyways.
Did you log the value of cell.text.contentSize.height ?
At that moment you don't get the correct value, I think you should set the height on the following UITableView callback:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
Try to add [cell.text layoutIfNeeded] before calling cell.text.contentSize
The contentSize will be unknown by the UITextField until it has been drawn. Calling layoutIfNeeded should force the computation of layout size.
If finaly made it work with this, try it
cell.text.attributedText = [[NSAttributedString alloc]initWithString:textString];
float textViewWidth = cell.text.frame.size.width;
[cell layoutIfNeeded];
cell.text.contentSize = [cell.text sizeThatFits:CGSizeMake(textViewWidth, FLT_MAX)];
[cell.text sizeToFit];

Resources