具有自动布局的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 }
由于您限制了标签的width
, intrinsicContentSize
尊重该width
并调整height
。 这就造成了鸡和鸡蛋的问题:
- 单元格的自动布局结果取决于标签的
intrinsicContentSize
- 标签的
intrinsicContentSize
取决于标签的width
- 标签的
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]; } }); }