6

I am facing an issue with auto sizing cells using Auto Layout. My goal is to achieve a table that will look something like this:

| Title_label (time)      $price |
|                                |
|Some long description. More     |
|description.                    |
|                                |

When the title is long it should look like this:

| This title is (time)    $price |
| really long                    |
|                                |
|Some long description. More     |
|description.                    |
|                                |

So when title gets bigger it pushes time label to the right as long as there is 8 points space beetwen time and price. If it is even bigger it should wrap to next line.

I have done before table view with self sizing cells but there where only one expanding label, not two.

I have implemented row's automatic height:

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 100

This is how my constraints look like:

|     8px
|8px title 8px time >=8px       price|
|     8px                            |
|8px description                  8px|
|     8px                            |

There is also top alignment between price time and title.

I've set lines number of title and description to 0. I've set compression resistance of time and price to 1000 (because title was overlapping them).

However the title label doesn't wrap to next line. It ends with .... What is more description label also is too small. When I scroll the table desription's height is fixed.

I've tried adding cell.layoutIfNeeded() before returning cell. Then cell layout gets messed up (title is clipped) but when I scroll tV everything is OK.

Any ideas?

Edit: Is this because title label is next to other labels and it doesn't know when it should wrap?

I tried

override func layoutSubviews() {
        self.nameLabel.preferredMaxLayoutWidth -= (durationLabel.frame.width + priceLabel.frame.width + 16)
        super.layoutSubviews()
    }

to tell title label what is its max width but it messes things up.

Cahir09
  • 501
  • 6
  • 14

4 Answers4

2

Just like you, I have set the rows of title and description to 0, and I have set up your cell like this:

|     8px
|8px title 8px time >=8px       price|
|     8px                            |
|8px description                  8px|
|     8px                            |

Then, I have set the compression and hugging properties:

title:

  • Hugging: H:251, V:252
  • Compression: H:999, V:1000

time:

  • Hugging: H:253, V:251
  • Compression: H:1000, V:750

price:

  • Hugging: H:252, V:251
  • Compression: H:1000, V:750

description:

  • Hugging: H:251, V:251
  • Compression: H:750, V:999

Everything works as expected

Daniel
  • 20,420
  • 10
  • 92
  • 149
  • Thanks for answer, unfortunately it doesn't work for me (without layoutIfNeeded()). After adding layoutIfNeeded() title label wraps but I get a lot of NSConstraints errors. And description is still truncated. – Cahir09 Jul 21 '15 at 09:51
  • I created new test project and set all constraints, compression and hugging properties as you suggested. But title is still truncated. If I add layoutIfNeeded before returning cell it looks fine but there is a bunch of layout constraints errors. The good news is that whole description is displayed. In my project data is loaded from WS and it's a little bit complicated to fill cell with appropriate data. Can it be the reason why description is cut off? I mean cell cannot calculate its height before it is displayed? If you still have your sample project, could you upload it and share a link? – Cahir09 Jul 22 '15 at 06:37
  • I only tried it on IB, but it worked. I'll setup a project once I have some spare time. – Daniel Jul 22 '15 at 07:46
2

enter image description hereYou can add constraint first to price as leading, top, height, width. then to time label as top, trailing,height,width. For title label as leading, trailing, top, bottom. For description label leading, trailing, top, bottom. & write the below code. heightForRowAtIndexPath will give you proper height to your cell

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static YOUR_TABLEVIEW_CELL *sizingCell = nil;
    static NSString *CellIdentifier=@"YOUR_TABLEVIEW_CELL_IDENTIFIER";
    sizingCell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (sizingCell==nil)
    {
        sizingCell=[[YOUR_TABLEVIEW_CELL alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    [self configureFareIssueCell:sizingCell atIndexPath:indexPath];
    return [self calculateHeightForConfiguredSizingCell:sizingCell];
}

//assign all the labels  here
- (void)configureFareIssueCell:(YOUR_TABLEVIEW_CELL* )cell atIndexPath:(NSIndexPath *)indexPath
{
    //e.g 
    cell.lbl.text=@"YOUR_TEXT";
    cell.imageView.image=[UIImage imageNamed:@"NAME_OF_YOUR_IMAGE"];
} 

- (CGFloat)calculateHeightForConfiguredSizingCell:(YOUR_TABLEVIEW_CELL *)sizingCell
{
    CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    return size.height + 1.0f; // Add 1.0f for the cell separator height
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   static NSString *CellIdentifier=@"YOUR_TABLEVIEW_CELL_IDENTIFIER";
   YOUR_TABLEVIEW_CELL   *cell =[tableView dequeueReusableCellWithIdentifier:@"YOUR_TABLEVIEW_CELL_IDENTIFIER"];
    if (cell==nil)
    {
        cell=[[YOUR_TABLEVIEW_CELL alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    [self configureFareIssueCell:cell atIndexPath:indexPath];

   return cell;
}  
swapnali patil
  • 304
  • 2
  • 17
2

Try adding

[cell layoutIfNeeded]

before returning your configured cell.

Stefan
  • 1,496
  • 1
  • 13
  • 26
0
  1. add minimum width the to the time & price lable

  2. set the hugging priorities too

title label:

Hugging: H: 1000, V: 1000

Compression: H: 1000, V:1000

description label:

Hugging: H: 1000, V: 999

Compression: H: 1000, V:999

  1. add this line in the end of the cellforRowAtIndexPath & remove layoutSubviews

    cell?.layoutIfNeeded()

  2. add this function

    func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension }

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension }

5 Build & run

Mihawk
  • 581
  • 4
  • 12