我有UITableView
个单元格,其固定高度为100磅。单元格在xib文件中创建,该文件使用3个约束将UILabel
固定到单元格contentView
的左,右和上边缘。标签的垂直拥抱优先级设置为1000,因为我希望单元格的高度尽可能小。
当xib文件中单元格的宽度设置为320磅时,与iPhone上的tableView宽度相同,autolayout按预期工作。但是,当我将单元格的宽度设置为小于320点时,我得到了意想不到的结果。 (我想在tableViews中使用具有不同宽度的相同单元格,例如在通用应用程序中)
例如:当我将宽度设置为224点并为标签提供一个文本,该文本占用该宽度的2行时,标签的高度将增加以适应2行,但是当单元格调整为320点时为了适应该宽度的tableView,文本只占用1行,但标签的高度保持在2行。
我在GitHub上放了一个示例项目来演示问题:https://github.com/bluecrowbar/CellLayout
有没有办法让UILabel
总是调整大小以拥抱其文字内容?
答案 0 :(得分:66)
在单元子类中添加它可以起作用:
- (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上找到了这个。
更新1:这个答案适用于iOS 7.我发现自iOS 8以来,表格视图单元格中的自动布局非常不可靠,即使对于非常简单的布局也是如此。经过大量的实验,我(大部分)回去做手动布局和手动计算细胞的高度。
更新2:我已经在iOS 9上运行了一些测试,似乎UITableViewAutomaticDimension
最终正如宣传的那样工作。耶!
答案 1 :(得分:14)
愚蠢的错误!我在这个问题上已经失去了将近一天,最后我用Steven Vandewghe的解决方案解决了这个问题。
Swift版本:
override func layoutSubviews() {
super.layoutSubviews()
self.contentView.layoutIfNeeded()
self.myLabel.preferredMaxLayoutWidth = self.myLabel.frame.size.width
}
答案 2 :(得分:3)
由于您限制了标签width
,intrinsicContentSize
尊重width
并调整height
。这就产生了鸡和蛋的问题:
intrinsicContentSize
intrinsicContentSize
取决于标签&{39} 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];
}
原始解决方案无法可靠地运行:
- (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];
}
});
}
答案 3 :(得分:0)
我通常将这两行添加到viewDidLoad()
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 96
这会自动调整单元格的大小
答案 4 :(得分:0)
我在iOS 12上使用XCode 10,但仍然出现自动布局问题,首次显示表格时,单元格的高度不正确。蒂莫西·穆斯(Timothy Moose)的回答并不能解决我的问题,但是根据他的解释,我想出了一个对我有用的解决方案。
我继承了UITableViewController的子类,并重写viewDidLayoutSubviews消息以检查宽度变化,如果宽度变化,则强制更新表。这样可以在显示视图之前解决该问题,使其看上去比我的其他工作要好得多。
首先将一个属性添加到您的自定义UITableViewController子类中,以跟踪先前的宽度:
@property (nonatomic) CGFloat previousWidth;
然后覆盖viewDidLayoutSubviews以检查宽度变化:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGFloat width = self.view.frame.size.width;
if (self.previousWidth != width) {
self.previousWidth = width;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
}
这解决了我的表格单元格有时最初被赋予错误的高度的问题。
答案 5 :(得分:0)
我知道这是一个老问题,但是也许UILabel子类也可以为某些问题提供帮助
class AutoSizeLabel: UILabel {
override var bounds: CGRect {
didSet {
if bounds.size.width != oldValue.size.width {
self.setNeedsUpdateConstraints()
}
}
}
override func updateConstraints() {
if self.preferredMaxLayoutWidth != self.bounds.size.width {
self.preferredMaxLayoutWidth = self.bounds.size.width
}
super.updateConstraints()
}
}
注意:在UILabel在StackView内时无法正确调整自身大小的情况下也适用