具有自动布局的UITableViewCell中的UILabel具有错误的高度

我有一个固定的高度为100点的单元格的UITableView 。 单元格是在xib文件中创build的,该文件使用3个约束将UILabel到单元格contentView的左侧,右侧和顶部边缘。 标签的垂直拥抱优先级设置为1000,因为我希望单元格的高度尽可能小。

当xib文件中单元格的宽度设置为320点时,与iPhone上的tableView宽度相同,自动布局按预期工作。 但是,当我把单元格的宽度设置为小于320点时,我得到了意想不到的结果。 (我想在tableViews中使用不同宽度的单元格,例如在通用应用程序中)

例如:当我将宽度设置为224点并为该标签提供了一个文本,该文本在该宽度处占用2行时,标签的高度将增加以适合2行,但是当单元格调整到320点以适合该宽度的tableView,文本只占用1行,但标签的高度保持在2行。

我已经在GitHub上放置了一个示例项目来演示这个问题: https : //github.com/bluecrowbar/CellLayout

有没有办法让UILabel总是resize来拥抱它的文本内容?

在单元格子类中添加这个工作:

 - (void)layoutSubviews { [super layoutSubviews]; [self.contentView layoutIfNeeded]; self.myLabel.preferredMaxLayoutWidth = self.myLabel.frame.size.width; } 

我在http://useyourloaf.com/blog/2014/02/14/table-view-cells-with-varying-row-heights.html上find了这个。

更新1:这个答案是针对iOS 7.我发现表格视图单元格中的自动布局是非常不可靠的,因为iOS 8,即使是非常简单的布局。 经过大量的实验,我(大部分)回去做手动布局和手动计算单元格的高度。

更新2:我已经在iOS 9上运行了一些testing,看起来UITableViewAutomaticDimension最终能像广告一样工作。 好极了!

愚蠢的错误! 我在这个问题上已经有将近一天的时间了,最​​后我用Steven Vandewghe的解决scheme解决了这个问题。

Swift版本:

 override func layoutSubviews() { super.layoutSubviews() self.contentView.layoutIfNeeded() self.myLabel.preferredMaxLayoutWidth = self.myLabel.frame.size.width } 

由于您限制了标签的widthintrinsicContentSize尊重该width并调整height 。 这就造成了鸡和鸡蛋的问题:

  1. 单元格的自动布局结果取决于标签的intrinsicContentSize
  2. 标签的intrinsicContentSize取决于标签的width
  3. 标签的width取决于单元格的自动布局结果

所以会发生什么是单元格的布局只计算一次,其中(2)是基于XIB文件中的静态宽度,这会导致错误的标签height

你可以通过迭代来解决这个问题。 也就是说,在通过第一次计算设置标签的width后重复自动布局计算。 在你的自定义单元格中这样的东西将工作:

 - (void)drawRect:(CGRect)rect { CGSize size = self.myLabel.bounds.size; // tell the label to size itself based on the current width [self.myLabel sizeToFit]; if (!CGSizeEqualToSize(size, self.myLabel.bounds.size)) { [self setNeedsUpdateConstraints]; [self updateConstraintsIfNeeded]; } [super drawRect:rect]; } 

原来的解决scheme不能可靠工作:

 - (void)layoutSubviews { [super layoutSubviews]; // check for need to re-evaluate constraints on next run loop // cycle after the layout has been finalized dispatch_async(dispatch_get_main_queue(), ^{ CGSize size = self.myLabel.bounds.size; // tell the label to size itself based on the current width [self.myLabel sizeToFit]; if (!CGSizeEqualToSize(size, self.myLabel.bounds.size)) { [self setNeedsUpdateConstraints]; [self updateConstraintsIfNeeded]; } }); }