Change height of UITextView in cellForRowAtIndexPath - uitableview

I'm trying to change the height of an UITextView which I have in a custom made Cell for my tableView.
The 'OverviewCell' is an identifier of this custom cell in a nib and also the UITextView 'postIntro' is dragged into the nib.
Sadly enough the height is not changing, only after i scrolled the height is changed. The cells which are visible without scrolling are just the default height from the nib.
When i try to change the height of the 'postImage' the same problem happens.
This is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"OverviewCell";
OverviewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Post *post = [self.posts objectAtIndex:[indexPath row]];
if(!cell)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"OverviewCell" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[OverviewCell class]])
{
cell = (OverviewCell *)currentObject;
break;
}
}
}
[[cell postImage] setImage:[UIImage imageWithData:post.image]];
[[cell postTitle] setText:post.title];
[[cell postIntro] setText:post.intro];
// Resize the intro textview so the text fits in.
CGRect frame = cell.postImage.frame;
frame.size.height = 20; //cell.postIntro.contentSize.height;
[cell.postIntro setFrame:frame];
NSLog([NSString stringWithFormat:#"Height of textView on indexpath %i is set to %f", indexPath.row ,cell.postImage.frame.size.height]);
return cell;
}
Any other suggestions to my code is welcome...

I finally got it working by changing the constraint of the UITextview in code.
I've created and IBOutlet which is attached to the constraint of the UITextview.
IBOutlet NSLayoutConstraint * postContentHeightConstraint;
After that I've set the constraint height to the specified height for the cell (contentSize).
self.postContentHeightConstraint.constant = self.postContent.contentSize.height;
After setting the new height to the constraint, call the layoutIfNeeded function on the UITextView
[self.postContent layoutIfNeeded];

Implement tableView:heightForRowAtIndexPath: in your table view delegate.
Update: To update the height of the UITextView after it has been created, call [cell.postIntro setNeedsLayout] after setting the frame

For changing the height of the UITextView, call
[tableView beginUpdates];
[tableView endUpdates];
after setting the new dimensions for the UITextView.
Questions this, and this will help with your problem.
Hope the answer helped!

Related

iOS - Auto resizing table view cells

I'm having some troubles with auto-resizing table view cells. I've been able to resize a cell's label based on its amount of text but I'm unable to adjust the cell height accordingly. Here's some code:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
_cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (_cell == nil)
{
_cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
PFObject *object = [_postsArray objectAtIndex:indexPath.row];
NSString *nameString = [object objectForKey:#"Name"];
_cell.cellLabel.text = [NSString stringWithFormat:#"Posted by %#", nameString];
_cell.cellPostLabel.text = [NSString stringWithFormat:#" %#", [object objectForKey:#"PostedDream"]];
[_cell.cellPostLabel sizeToFit];
[tableView setAutoresizesSubviews:YES];
NSLog(#"cell post label height: %f", _cell.cellPostLabel.frame.size.height);
return _cell;
}
Things to note are that I am using a custom table view cell called TableViewCell *cell subclassed from UITableViewCell and the cell and its labels were added through IB.
The label that's being adjusted is cellPostLabel and it adjusts perfectly depending on the amount of text, but it gets cut off due to the cell not adjusting as well.
I also tried calling [self.tableView setAutoresizesSubviews:YES]; and
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight; in viewDidAppear: but still nothing. Any suggestions would be appreciated.
Cell height is determined by heightForRowAtIndexPath method.
You can implement that method on your viewcontroller and return height you prefer.
If your cell should have different height you should implement that method and return different value each cells. Or not just return static value or set tableview's property rowHeight, in this case you don't need to implement that method.

cell.contentView systemLayoutSizeFittingSize: does not work for dynamic height tableview

I tried to use autolayout in custom uitableviewcell
And tried to implement the dynamic height according to this SO topic
Using Auto Layout in UITableView for dynamic cell layouts & variable row heights
But my cell is created by xib file. So the method is somewhat different
Here is my code in heightForRowAtIndexPath
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
myDataItem *item= [[data items] objectAtIndex:[indexPath row]];
CustomCell *cell = [self.offscreenCells objectForKey:#"CustomCell"];
if (!cell) {
cell = [CustomCell alloc] init];
[self.offscreenCells setObject:cell forKey:#"CustomCell"];
}
[cell.commentView setText:item.comment];
[cell.displayNameView setText:item.displayNameOfItemOwner];
[cell.timeAgoView setText:item.timeAgo];
[cell.imageView setImage:[UIImage imageNamed:#"sis_profile_placeholder"]];
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(_prototypeCell.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height+1; }
And the height that I got from [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] is alway "nil"
"
When I tried to debug ,I found that all subviews of my customcell are "nil" but the cell itself is not "nil". This might because the customCell of mine is made by nib and when I do [[CustomCell alloc] init] the cell is not fully created.
But I did tried to change method to cell = [_tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
The result is still the same. Every subview is nil . This make the height return to be zero and the make my tableView display incorrectly. Are there any way to solve this ?
I tried to make these upon AutoLayout .Actually, in the previous version ,that I didn't use AutoLayout and calculate the cell height manually .It did work perfectly. Anyway, I just want to tried AutoLayout.
Please help .Thanks in advance
Here is my solution
I alloc new cell by
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
myDataItem *item= [[data items] objectAtIndex:[indexPath row]];
CustomCell *cell = [self.offscreenCells objectForKey:#"CustomCell"];
if (!cell) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
[self.offscreenCells setObject:cell forKey:#"CustomCell"];
}
[cell.commentView setText:item.comment];
[cell.displayNameView setText:item.displayNameOfItemOwner];
[cell.timeAgoView setText:item.timeAgo];
[cell.imageView setImage:[UIImage imageNamed:#"image"]];
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(_prototypeCell.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height+1; }
As far as I know, under iOS 8 the proposed solution is not going to work for cells with multiline labels because systemLayoutSizeFittingSize will not take into account the desired cell width (simply put, it will try to layout the label into a single line, thus making the cell wider than it should).
I managed to solve this issue by installing a width constraint in cell's contentView instead of setting the cell bounds. Remember to uninstall such constraint right after calling systemLayoutSizeFittingSize:.

UITableViewCell not relaying/repainting

I'm trying to have a label in a UITableViewCell that can span two lines, but if there is only one line align it vertically to the first line.
The code to work out the label height (below) seems to work, but the label isn't getting relaid/repainted. If I scroll the cell off the view and back again, the label has the correct height.
I have tried [cell setNeedsLayout], [cell setNeedsDisplay], [titleLabel setNeedsLayout] and [titleLabel setNeedsLayout, and no combination has worked.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ItemCell" forIndexPath:indexPath];
Item *item = (self.items)[indexPath.section][indexPath.row];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
titleLabel.text = item.title;
titleLabel.backgroundColor = [UIColor redColor];
// Some titles span two lines, so resize to fit the new content.
CGRect textRect = [titleLabel.attributedText boundingRectWithSize:CGSizeMake(titleLabel.frame.size.width, CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil];
CGRect labelRect = CGRectIntegral(CGRectMake(titleLabel.frame.origin.x,
titleLabel.frame.origin.y,
titleLabel.frame.size.width,
textRect.size.height));
NSLog(#"%#, %f", titleLabel.text, labelRect.size.height); // This logs out the correct height
titleLabel.frame = labelRect;
return cell;
}
please try my suggestion. may be it will help you with the reusability of cell in UITableview. Please Check the following points in you code:
What to do if you cell == nil while redrawing UITableView in iPhone. thats why you have to make condition like below for reusability of UITableViewCell.
// Get table View Cell
static NSString *CellIdentifier = #"ItemCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib;
nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (UITableViewCell *) [nib objectAtIndex:0];
}
Please test it and let me know.
Turns out I'm using auto layout, which means I can't set the frame directly. Instead I need to add a height constraint and connect it to an IBOutlet on my UITableViewCell subclass.

Adjusting elements and the height of UITableView on scroll

I have a UITableView with multiple UILabels. The issue is that the text in these cells change dynamically as I receive data from the server. It works fine when I load the view controller. But as I scroll, the height of the cells are not updated as heightForRowAtIndexPath is only called once.
Here are the screenshots:
As I've shown in the screenshot, the question label reduces in size which leads to a gap (shown by arrow).
Here's my cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIndentifier = #"CustomCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIndentifier];
if (cell == nil)
{
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIndentifier];
}
cell.question.autoDetectLinks = YES;
// Used to populate cell from NSDictionary
[self setDataToCell:cell AtIndexPath:indexPath];
return cell;
}
Here's my custom cell's layoutSubviews:
- (void) layoutSubviews
{
CGRect frame = self.question.frame;
frame.size.width = 277.0f; //you need to adjust this value
self.question.frame = frame;
self.question.numberOfLines = 2;
[self.question sizeToFit];
// Place time below question
CGRect timeFrame = self.time.frame;
timeFrame.origin.y = self.question.frame.origin.y + self.question.frame.size.height + 5;
self.time.frame = timeFrame;
[self.time sizeToFit];
}
So to tackle this situation I called
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[_tableIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
in - (void) scrollViewDidScroll:(UIScrollView *)scrollView
This solves my problem but reduces the performance and the elements jump around before settling even after setting the animation as UITableViewRowAnimationNone. Is there a better way of doing it? Should I call reloadRowsAtIndexPaths somewhere else?
Thanks.
Ok here come the edited answer:
The problem is your sizeToFit in your layoutSubviews. Just follow this link to resolve your issue:
here
If you also want the cell and the label to dynamically resize to their corresponding text but at the same time your timelabel to be directly underneath it you will have to determine the size of your uilabel based on the text, font and font-size.
See here for more information:
here

Cells Labels Not Resizing Until Table Scrolling

I'm using this code to resize the labels that maintains the titles of my cells. The problem is that the cells labels are not resizing until I scroll the table. Cells need to disappear to resize their labels correctly. What can I do to get all the cells labels well resized without having to scroll previously?
Thanks for reading.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ExampleTableViewCell *cell = (ExampleTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"ExampleTableViewCell"];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ExampleTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.title.text = [self.test objectAtIndex:[indexPath row]];
//Calculates the expected size based on the font and linebreak mode of the label.
CGSize maximumLabelSize = CGSizeMake(200, [UIScreen mainScreen].bounds.size.width);
CGSize expectedLabelSize = [cell.title.text sizeWithFont:cell.title.font constrainedToSize:maximumLabelSize lineBreakMode:cell.title.lineBreakMode];
// Adjusts the label the the new height.
CGRect newFrame = cell.title.frame;
newFrame.size.height = expectedLabelSize.height;
cell.title.frame = newFrame;
return cell;
}
Try to write the same code in
willDisplayCell method of UItableViewController
Another approach is .... in your ExampleTableViewCell class implement
- (void)layoutSubviews{
}
set your title's frame in above function. It should work
you must implement the method heightForRowAtIndexPath and return the height of cell then your problem solved :-)
I found Matt Long's solution really helpful (http://www.cimgf.com/2009/09/23/uitableviewcell-dynamic-height/).

Resources