1

I have a custom UITableViewCell with only one UILabel. The UILabel is potentially too long to fit as a single row, so I have to dynamically set the height of UITableViewCell.

I set leading, top, and height(Greater or equal) constraints of UILabel. Am I missing any constraints?

ProductDetailDescriptionTableViewCell *cell = (ProductDetailDescriptionTableViewCell *)[self productDetailDescriptionCellInTableView:tableView
                                                                                                      indexPath:indexPath];

CGSize cellSize = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

return cellSize.height + 1;

This is calculate height code in tableView:heightForRowAtIndexPath:

I also set preferredWith of UILabel.

When I run my code, the height of cell is 0, label`s frame is

(0,-21,42,21)

I wish someone can help. Thank you very much!!!

Dh S
  • 13
  • 5

4 Answers4

0

May be it's logic help full for you. Make Sure your label line is set 0.(label.numberOfLines = 0).It's work for me.

//Count Cell Size Here - It’s depend on content size of label. Put requiredHeight method in Tableviewcell class.
    - (CGFloat)requiredHeight
    {
        CGSize labelSize = [label.text sizeWithFont: [label font]
                                              constrainedToSize: CGSizeMake(300.0f, 300.0f)
                                                  lineBreakMode: NSLineBreakByTruncatingTail];

        int RowHeight = 30.0f + labelSize.height;

        if (RowHeight < 44) {
            if ([UIScreen mainScreen].bounds.size.width == 320) { // iPhone4 & iPhone5
                 return 45.0f;
            } else if([UIScreen mainScreen].bounds.size.width == 375){ // iPhone6
                 return 54.0f;
            }else{// iPhone6Plus
                 return 59.0f;
            }

        }else{

            if ([UIScreen mainScreen].bounds.size.width == 320) { // iPhone4 & iPhone5
               return 30.0f + labelSize.height;
            } else if([UIScreen mainScreen].bounds.size.width == 375){ // iPhone6
                //return 54;
                return 40.0f + labelSize.height;
            }else{// iPhone6Plus
               //return 59;
                 return 45.0f + labelSize.height;
            }
        }
    }


    //Call your custom cell class here
    - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

         ATableViewCell *cell = (ATableViewCell*)[self tableView:self->tableView cellForRowAtIndexPath:indexPath];
         return [cell requiredHeight];

    }
Ashish Kakkad
  • 23,586
  • 12
  • 103
  • 136
Renish Dadhaniya
  • 10,642
  • 2
  • 31
  • 56
  • Thank you!!! It worked. But I want to know why `[cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]` doesn`t work? – Dh S May 15 '15 at 08:02
  • @DhS, Please review this:http://stackoverflow.com/questions/20308402/when-i-use-auto-layout-to-choose-each-cells-height-so-theyre-dynamic-it-most. If anwer is right then please accept that so it's useful for others. – Renish Dadhaniya May 15 '15 at 08:44
  • Could you tell me what is the meaning of these magic numbers? – Dh S May 15 '15 at 08:52
  • @DhS, This is not magic number my dear friend. It's minimum size of cell setting in different devices.Default cell size 44 for normal devices, iPhone6 54 and iPhone6Plus 59. – Renish Dadhaniya May 15 '15 at 09:08
  • Those _are_ magic numbers. This isn't maintainable - it will need to be updated every time Apple bring out a new phone. – Corwin Newall Sep 29 '15 at 22:46
  • @CorwinNewall, Starting with iOS 8 you should maintain dynamic height very easy way. You just need to put below two line code in ViewDid load.(self.tableView.estimatedRowHeight = 100.0; self.tableView.rowHeight = UITableViewAutomaticDimension;). Make sure it is support with Autolayout and starting with iOS8. One another thing is, you do not apply fix constraint of label height other wise it is not working. My above solution is for iOS6 and iOS7 and later versions. Thank you very much for your comments. – Renish Dadhaniya Sep 30 '15 at 04:30
0

Change the frame of the special cell(s) in like:

 float longLabelRowHeight; // Just for demonstration

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    CGSize constraint = CGSizeMake(self.frame.size.width, 9999);
    CGSize size = [label.text sizeWithFont:label.font 
           constrainedToSize:constraint 
               lineBreakMode:UILineBreakModeWordWrap];

    longLabelRowNumber = indexPath.row; //Just for demonstration

    longLabelRowHeight = size.height;

    if (longLabelRowHeight > 44.f) { // or whatever size
        cell.frame.size = CGSizeMake(self.frame.size.width, longLabelRowHight)
    }
}

Also be sure to return the custom height like:

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row == longLabelRowNumber) { //Just for demonstration
        return longLabelRowHeight;
    }
    else {
        return kNormalCellHeight;
    }
}
Jeshua Lacock
  • 5,730
  • 1
  • 28
  • 58
0

Update

I have created an example project for you, check it here.

Original answer

I think the simplest approach is the following:

  1. Define leading, top, trailing, and bottom constraints between your label, and the cell's content view (no need to constrain the height).

Constraints

  1. Now on your label, set the number of lines to 0 (meaning that it will fit its text into as many rows as needed):

Lines

This way, it should always fit within your table view cell, and the text won't be truncated. I'm not sure that setting the row height to automatic like, since it's supposed to be the default, but you can do it like this: self.tableView.rowHeight = UITableViewAutomaticDimension;

If you run into any issues, I recommend this terrific article on self sizing cells.

József Vesza
  • 4,775
  • 3
  • 27
  • 42
  • I'm not sure I understand the question, but I roughly meant the following: UILabel.leading = contentView.leading + X, contentView.trailing = UILabel.trailing + Y, contentView.top = UILabel.top + Z, contentView.bottom = UILabel.bottom + W (X, Y, Z, W are arbitrary constants). This way you'll have the same padding around the label no matter the size. – József Vesza May 15 '15 at 07:44
  • @DhS I have uploaded an example project for you, check it out. :) – József Vesza May 15 '15 at 08:01
  • Thank you for your example project. Is there no need to implement heightForRow method? – Dh S May 15 '15 at 08:45
  • No. The constraints will make sure your layout is correct. – József Vesza May 15 '15 at 08:46
  • I delete heightForRow method, and set self.tableView.rowHeight = UITableViewAutomaticDimension, and set left, top, bottom, right constraints, but warning here. 'Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead' – Dh S May 15 '15 at 10:49
  • I think you also need to add an estimate for the self-sizing to kick in, like so: `self.tableView.estimatedRowHeight = 100`. In the example I shared, it works well when used together with `self.tableView.rowHeight = UITableViewAutomaticDimension` – József Vesza May 15 '15 at 10:52
0

If you want to just display text into label you do not have to make custom cell.

Just make number of line of UILabel to 0(zero)

Example

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}

cell.textLabel.text = @"This Is an example for dynamic height of UITableviewcell and UILabel in UITableView";
cell.textLabel.numberOfLines = 0;
return cell;

}

You do not have to specify heightForRowAtIndexPath Method

iDhaval
  • 3,175
  • 1
  • 11
  • 21