romaonthego / RETableViewManager

Powerful data driven content manager for UITableView.
MIT License
2.48k stars 430 forks source link

How does it work with AutoLayout? #220

Open jianghaoyuan2007 opened 9 years ago

jianghaoyuan2007 commented 9 years ago

When I using this library set a variable height of cell, what's the best way?

for example:

sebastianludwig commented 9 years ago

I'm assuming you're using custom designed cells?

I just had good success by basically following this guide and looking at the mentioned example project. I've used IB to set to constraints though.

The key points are to implement layoutSubviews of your custom cell class like this

- (void)layoutSubviews
{
    [super layoutSubviews];

    [self.contentView setNeedsLayout];
    [self.contentView layoutIfNeeded];

    self.body.preferredMaxLayoutWidth = CGRectGetWidth(self.body.frame);
}

Register your VC as RETableViewManagerDelegate, keep a reference to an offscreen cell obtained with heightCalculationCell = [tableView dequeueReusableCellWithIdentifier:@"TwoLineItem"]; and implement

- (CGFloat)tableView:(UITableView *)tv heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    heightCalculationCell.header.text = @"heading";
    heightCalculationCell.body.text = content[indexPath.row];

    [heightCalculationCell updateConstraints];

    heightCalculationCell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tv.bounds), CGRectGetHeight(heightCalculationCell.bounds));

    [heightCalculationCell layoutSubviews];

    CGFloat height = [heightCalculationCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    return height + 1;
}

@romaonthego it would be nice to get the reference to the item passed into the delegate, to be able to react to properties like the accessoryType. What's your opinion about a tableView:heightForRowAtIndexPath:forItem: delegate method which is called instead of tableView:heightForRowAtIndexPath if implemented?

sebastianludwig commented 9 years ago

I just found out that is possible with implementing the class method +heightWithItem:tableViewManager:.

static TwoLineCell *heightCalculationCell = nil;

@implementation TwoLineCell

+ (CGFloat)heightWithItem:(TwoLineItem *)item tableViewManager:(RETableViewManager *)tableViewManager
{
    if (!heightCalculationCell) {
        heightCalculationCell = [tableViewManager.tableView dequeueReusableCellWithIdentifier:@"TwoLineItem"];
    }

    heightCalculationCell.item = item;
    [heightCalculationCell cellWillAppear];
    [heightCalculationCell layoutSubviews];
    [heightCalculationCell updateConstraints];

    heightCalculationCell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableViewManager.tableView.bounds), CGRectGetHeight(heightCalculationCell.bounds));

    [heightCalculationCell layoutSubviews];

    CGFloat height = [heightCalculationCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    return height + 1;
}
sebastianludwig commented 9 years ago

However, to implement row height caching, the heightWithItem solution is not sufficient and we're back to tableView:heightForRowAtIndexPath:forItem:. Fancy a PR @romaonthego?

wayne798 commented 7 years ago

@sebastianludwig I tried your code, but failed, I create the cell with pure code not xib. Can you give more code segment?

sebastianludwig commented 7 years ago

@wayne798 can you elaborate on "failed"? What exactly is the problem? Can you provide a demo project showcasing your issue?

wayne798 commented 7 years ago

@sebastianludwig Aha,I resolved it , I changed "heightCalculationCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;" to "heightCalculationCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;" , then it worked well. I googled "systemLayoutSizeFittingSize" , there are some issues like me. I use Xcode8.1 ans iOS10.2