0

I designed a custom UITableViewCell by adding some subviews in the cell's contentView, I also added some auto layout constraints between the contentView and the subviews.

But when I debug the app, Xcode tells me that there is a constraint conflict. In the list of constraint, there is one NSAutoresizingMaskLayoutLayoutConstraint that limits the cell height to be 43, so Xcode break the constraint of my subview height and 'compress' it.

I have tried:

  1. In Interface builder, uncheck the "autoreize subviews" checkbox. Doesn't work.

  2. In code, cell.contentView.translatesAutoResizingMaskIntoConstraints = NO. This causes the app to crash with an exception: "Auto Layout still required after executing -layoutSubviews". I have tried every proposed solution in this question: "Auto Layout still required after executing -layoutSubviews" with UITableViewCell subclass None of them work for me.

So I guess I can only let the cell do its autoresizing thing, and remove the auto resizing constraint in code. How should I do it without breaking things?

EDIT: Or, from another perspective, how I can make the tableViewCell height flexible (changes with subview height and constraints)? In IB, I have to set its height, right?

Community
  • 1
  • 1
NeoWang
  • 17,361
  • 24
  • 78
  • 126
  • There must be some layout conflicts. Create some sample project and share with us. Then its easy to figure it out. If you want to know how to create dynamic cell height with auto layout then i created some sample project that i can share it here. – Subramanian P May 09 '14 at 07:12

2 Answers2

1

You DON'T need to set cell.contentView.translatesAutoResizingMaskIntoConstraints = NO

In order to get the flexible height in UITableViewCells in autolayout you need to manually compute for the height in - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

Yes this tedious, but there is no other way. To calculate the height automatically you need to fulfill two conditions in your UITableViewCell:

  1. You must make sure all your subviews have translatesAutoResizingMaskIntoConstraints=NO
  2. Your cell subview's constraints must be pushing against the top and bottom edges of the UITableViewCell.

Then in your - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath, You need to recreate that cell for the specific indexPath and compute the height manually for that cell.

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

 //Configure cell subviews and constraints
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
 [self configureCell:cell forIndexPath:indexPath];

 //Trigger a layout pass on the cell so that it will resolve all the constraints.
 [cell setNeedsLayout];
 [cell layoutIfNeeded];

 //Compute the correct size of the cell and get the height. This is where the magic happens.
 CGFloat height = [cartItemCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    height += 1.0f

 return height;

}

Take note that systemLayoutSizeFittingSize is wonky with UITextViews. In that case you have to compute the height of the entire cell manually using another way. There are also some performance optimizations you can do by caching the height per indexPath.

This blog post has a a more detailed description on what to do but the gist is essentially what I mentioned above. : http://johnszumski.com/blog/auto-layout-for-table-view-cells-with-dynamic-heights

mj_jimenez
  • 443
  • 2
  • 5
  • Thanks! I guess my problem is that I used Interface builder to layout the subviews. And IB by default define a fixed height for the cell, which is translated into a layout constraint and cause conflicts. So your suggestion is that I drop the .xib file and write code to layout the subviews, right? – NeoWang May 09 '14 at 09:00
  • Or is there any way to remove the fixed height of cell in interface builder? Laying out the views with code is, as you said, very tedious, as there are many margin constraints. – NeoWang May 09 '14 at 09:04
  • Actually, you don't need to drop the IB to implement tableView:heightForRowAtIndexPath. As long as you implement tableView:heightForRowAtIndexPath in code in your UITableViewDelegate(most likely your UITableViewController), you can still change the height of the cell row. If the constraints are already set in, you can configure the cell by just add whatever content you need in the cell (UILabel, etc.) to expand it and call systemLayoutSizeFittingSize. – mj_jimenez May 10 '14 at 01:43
1

I have created some sample code for dynamic tableview cell height with auto layout. You can download the project using following link.

DynamicTableViewCellHeight

I hope this will help you.

Subramanian P
  • 4,365
  • 2
  • 21
  • 25