如何布局不同高度的自定义UITableViewCell

时间:2014-01-28 18:56:26

标签: ios iphone uitableview layoutsubviews

我有一个UITableViewCell子类,它有一个图像,标题和描述。 我应该根据描述内容长度调整单元格高度,即如果它跨越超过5行,我应该扩展它(+其他子视图,如图像等),直到它持续。

接下来的细胞应该在此之后开始。

我的UITableViewCell子类是从xib实例化的,它具有固定的行高= 160。

我知道这是非常标准的要求,但我找不到任何准则。

我已经像这样扩展了layoutSubViews:

- (void) layoutSubviews
{
    [self resizeCellImage];
}

- (void) resizeCellImage
{
    CGRect descriptionRect = self.cellDescriptionLabel.frame;
    CGRect imageRect = self.cellImageView.frame;

    float descriptionBottomEdgeY = descriptionRect.origin.y +  descriptionRect.size.height;
    float imageBottomEdgeY = imageRect.origin.y + imageRect.size.height;

    if (imageBottomEdgeY >= descriptionBottomEdgeY)
        return;

    //push the bottom of image to the bottom of description
    imageBottomEdgeY = descriptionBottomEdgeY;

    float newImageHeight = imageBottomEdgeY - imageRect.origin.y;
    imageRect.size.height = newImageHeight;
    self.cellImageView.frame = imageRect;

    CGRect cellFrame = self.frame;
    cellFrame.size.height = imageRect.size.height + imageRect.origin.y + 5;

    CGRect contentFrame = self.contentView.frame;
    contentFrame.size.height = cellFrame.size.height - 1;
    self.contentView.frame = contentFrame;

    self.frame = cellFrame;
}

它几乎告诉我,如果描述高于图像,我们必须调整图像大小以及单元格高度以适应描述。

但是,当我通过这样做调用此代码时:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    cell.cellDescriptionLabel.text = @"Some long string";
    [cell.cellDescriptionLabel sizeToFit];
    [cell setNeedsLayout];

    return cell;    
}

看来虽然由于layoutSubViews调用而更改了单元格框架,但其他单元格却不尊重它。也就是说,如果先前的单元格不会自行调整大小,它们就出现在相同的位置。

两个问题:

  • 如何使我想要的东西成为可能?
  • 我是否在setNeedsLayout内致电cellForRowAtIndexPath

PS:我知道heightForRowAtIndexPath是改变单元格高度的关键,但我觉得我作为cellForRowAtIndexPath的一部分进行的数据解析(此处未显示)对于计算来说是一种过度杀伤高度。我需要能够直接告诉UITableViewCell根据内容需要调整自身大小的内容。

3 个答案:

答案 0 :(得分:3)

-tableView:heightForRowAtIndexPath:是设计如何计算可变大小的单元格。单元格的实际框架并不重要,并且可以通过表格视图进行更改以满足其需要。

你有点想到这一点。委托告诉表格视图如何绘制单元格,然后表格视图强制单元格适合这些特征。您需要为单元提供的唯一内容是它需要保存的数据。

这是因为表格视图在有任何要绘制的单元格之前计算所有单元格的所有高度。这样做是为了允许表视图正确地调整其滚动视图的大小。它允许通过桌面视图适当调整大小的滚动条和平滑的快速平底锅。仅当表视图认为需要将单元格显示在屏幕上时才会请求单元格。


更新:如何获得单元格高度

我不得不这样做几次。我的视图控制器保留了一个从未在表视图中使用的单元格。

@property (nonatomic) MyTableViewCell *standInCell;

当我需要测量时,我会使用这个单元作为支架。我确定没有可变大小视图的单元格的基本高度。

@property (nonatomic) CGFloat standInCellBaseHeight;

然后在-tableView:heightForRowAtIndexPath:中,我获得所有可变大小视图的高度以及该索引路径的实际数据。我将可变尺寸的高度添加到我的支架中的单元底座高度。我返回新的计算高度。

注意,这都是非自动布局。我确信这种做法与此类似,但并不完全相同,但我没有经验。

答案 1 :(得分:1)

-tableView:heightForRowAtIndexPath:是告诉tableview其单元格大小的首选方法。您可以预先计算并将其缓存在字典中并重复使用,或者在ios7中,您可以使用-tableView:estimatedHeightForRowAtIndexPath:来估算尺寸。

答案 2 :(得分:1)

看一下这个帖子 - https://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights,答案指向一个非常好的示例项目 - https://github.com/caoimghgin/TableViewCellWithAutoLayout

很抱歉,但据我所知,您必须实施tableView:heightForRowAtIndexPath:。警告,在iOS 6中,这会立即调用UITableView中的每一行,我想绘制滚动条。 iOS7引入了tableView:estimatedHeightForRowAtIndexPath:,如果实现它允许您在进行所有计算之前猜测高度。这可以在非常大的桌子上提供很多帮助。

我发现效果很好的只是让tableView:heightForRowAtIndexPath:调用cellForRowAtIndexPath:来获取该行的单元格,然后查询该单元格的高度cell.bounds.size.height并返回该值。

这适用于小型表或在实现tableView:estimatedHeightForRowAtIndexPath的iOS7中。