0

I am using Autolayout and have a customised UITableViewCell that contains UITextView. The height of the cell and text view should be dynamically resized to accomodate larger contents.

Following answers from these links resize ui text view to its content and dynamic ui text view, I have used a height constraint on the text view and set its value to the height of the content. This does the job of accommodating the textView, but it is overshooting the cell. I have tried options like adjusting the size of the cell also but none of them have helped. Surprisingly, sizeToFit seems to have no effect. Here is the code I am using:

+ (SongAdditionalTextCell *)resize:(SongAdditionalTextCell *)additionalTextCell{
UITextView *textView = additionalTextCell.additionalText;
CGSize sizeThatFitsTextView = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, MAXFLOAT)];
NSLog(@"content height is %f, frame height is %f", textView.contentSize.height, textView.frame.size.height );
additionalTextCell.addnlTextHeightConstraint.constant = sizeThatFitsTextView.height;
return additionalTextCell;
}

Please see the attached image of the view (text view is second cell). any suggestions appreciated? dynamic text view second cell

Community
  • 1
  • 1
Gaurav Abbi
  • 645
  • 9
  • 23
  • Try this links.. http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout and http://nonsequiturs.com/articles/building-totem-2-0-dynamic-uitableviewcell-height-for-custom-cells-in-ios-7/ This definitely help for you. – Ashok Londhe May 04 '15 at 09:17
  • sizeToFit is deprecated see this for alternate http://stackoverflow.com/questions/18903304/replacement-for-deprecated-sizewithfontconstrainedtosizelinebreakmode-in-ios – Ajumal May 04 '15 at 09:55
  • Why not use constraints in the cell so that text view is pinned left, right, top and bottom. Then the cell should automatically grow when you change the text for the cell. You should only need to reload the row when you change the data model for the cell. You only need to calculate the height if you need to run pre-iOS8. So I would remove the height constraint as it seems redundant and replace that with edge pins. You could leave a height if you wish which is >= some size if you want a minimum cell height. – Rory McKinnel May 04 '15 at 10:45
  • @RoryMcKinnel, I have tried that and that always seemed the most logical thing to do after i went through most of the links including from apple dev center and many tutorials, but results were never as expected, may be i missed something, so the question to ask, if I have all the four constraints set, what else i need to do to get the table view cell height to conform to the content.I have tried doing this self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.estimatedRowHeight = 44;, but this leads to a UI where my first cell takes all the screen – Gaurav Abbi May 04 '15 at 11:06
  • Have you made sure in `estmatedHeightForRowAtIndexPath` that you return `UITableViewAutomaticDimension`? Also set `self.tableView.rowHeight = UITableViewAutomaticDimension`. This answer is useful: http://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights – Rory McKinnel May 04 '15 at 12:14

3 Answers3

0

Try this it working for me

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 {
     CGSize labelSize = [[[Array objectAtIndex:indexPath.row] valueForKey:@"detail"] sizeWithFont:[UIFont boldSystemFontOfSize:10]  constrainedToSize:CGSizeMake(255, MAXFLOAT)                                                                                         lineBreakMode:NSLineBreakByWordWrapping];
     return labelSize.height +15;
  }

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
     static NSString *simpletableidentifier=@"simpletableidentifier";
     UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:simpletableidentifier];
     if(cell == nil)
     {
        cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpletableidentifier];

         CGSize labelSize = [[[Array objectAtIndex:indexPath.row] valueForKey:@"detail"] sizeWithFont:[UIFont boldSystemFontOfSize:10]  constrainedToSize:CGSizeMake(255, MAXFLOAT)                                                                                         lineBreakMode:NSLineBreakByWordWrapping];

          UILabel *desc=[[UILabel alloc]initWithFrame:CGRectMake(35,2,245,labelSize.height)];
          desc.backgroundColor=[UIColor clearColor];
          desc.tag=2;
          desc.numberOfLines=0;
          desc.lineBreakMode=NSLineBreakByWordWrapping;
          desc.font=[UIFont boldSystemFontOfSize:10];
          desc.textColor=[UIColor whiteColor];
          [cell.contentView addSubview:desc];
     }
     NSString *Str3 = [[Array objectAtIndex:indexPath.row] valueForKey:@"detail"];
     UILabel *desc=(UILabel *)[cell.contentView viewWithTag:2];
     desc.text=Str3;

     cell.selectionStyle=UITableViewCellSelectionStyleNone;
     cell.backgroundColor=[UIColor clearColor];
     cell.contentView.backgroundColor=[UIColor clearColor];
     return cell;
}
  • In iOS8+, this will give you layout problems as `dequeueReusableCellWithIdentifier` returns a cell which has no superview and hence no size class associated with it. You should be using `dequeueReusableCellWithIdentifier:forIndexPath`. – Rory McKinnel May 04 '15 at 11:09
  • @RoryMcKinnel i forgot write `cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpletableidentifier];` – Chirag D jinjuwadiya May 04 '15 at 11:13
  • This line: `UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:simpletableidentifier];` should be: `UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:simpletableidentifier forIndexPath:indexPath];`. It should also never return nil meaning you do not need the check `if (cell == nil)`. – Rory McKinnel May 04 '15 at 12:07
0

I use this one:

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
        if (indexPath.row == 2)
    {
        NSString *cellText = @"init some text";
        CGSize labelSize    = [self calculateTextSize:cellText];

        return labelSize.height + 20.0f;
    }

    return 45;
}


- (CGSize) calculateTextSize: (NSString*) text
{
    UIFont *cellFont = [UIFont fontWithName:@"HelveticaNeue" size:12.0];

    CGFloat width = CGRectGetWidth(self.tableView.frame) - 40.0f;
    CGSize constraintSize = CGSizeMake(width, MAXFLOAT);

    CGRect labelRect = [cellText boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:cellFont} context:NSLineBreakByWordWrapping];

    CGSize labelSize = labelRect.size;

    return labelSize;
}

CGFloat width = CGRectGetWidth(self.tableView.frame) - 40.0f; - Calculation of the maximum available width of the text, you can use self.view.frame or etc. - 40.0f - because i have indentation from the edge = 20.0f

OMGHaveFun
  • 838
  • 1
  • 10
  • 16
0

Finally figured it out. @RoryMcKinnel's comment does help. Here's what I did in case it can help others. The problem was that I had two type of cells, one where I need to adjust the height (additionalText) and one where I do not need to do that. In the raw version, I override both estmatedHeightForRowAtIndexPath and heightForRowAtIndexPath and in both methods if the index is for row which is additionalText, I send UITableViewAutomaticDimension else I send the frame height. Of course refinements can be done :) to send better values, but the core concept is same.

here is the code.

    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (self.additionalTexts[@((long) indexPath.row)] != nil){
        return UITableViewAutomaticDimension;
    } else return [[SongTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainCellIdentifier].frame.size.height;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (self.additionalTexts[@((long) indexPath.row)] != nil){
        return UITableViewAutomaticDimension;
    } else return [[SongTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainCellIdentifier].frame.size.height;
}

and the resulting screen looks liketable view after fix

Gaurav Abbi
  • 645
  • 9
  • 23