具有相对约束的自动布局不影响systemLayoutSizeFittingSize:用于UITableViewCell

时间:2014-11-21 14:52:16

标签: ios objective-c uitableview autolayout

我有UITableView动态高度UITableViewCell,我正在使用自动布局来计算主题上this excellent answer的高度。到目前为止一切都很好。

我正在调整应用程序以使用更大的iPhone(6和6 Plus)屏幕尺寸,而且它大部分非常简单。

然而,在我的一些单元格中,我有一个图像,我想要跨越单元格的整个宽度,我希望图像的高度与图像的宽度成比例(0.55 *宽度,具体而言)。到目前为止,基于iPhone 6/6 Plus之前的标准320px纵向表视图宽度,我在自动布局约束中硬编码了图像的宽度和高度。

我认为像这样添加相对高度约束会很简单(我正在使用PureLayout):

[self.myImage autoMatchDimension:ALDimensionHeight 
                     toDimension:ALDimensionWidth 
                          ofView:self 
                  withMultiplier:0.55f 
                        relation:NSLayoutRelationGreaterThanOrEqual];

如果您不熟悉PureLayout,则会转换为对

的调用

[NSLayoutConstraint constraintWithItem: attribute: relatedBy: toItem: attribute: multiplier: constant:0.0f]

还有其他约束将它的边缘固定到superview,即UITableViewCell contentView。

然而,当我在单元格的 contentView 上调用systemLayoutSizeFittingSize:时,它似乎完全忽略了相对高度约束,并且得到的单元格高度太小而无法适应图像。

如果我设置了显式高度约束而不是相对高度约束,则没有问题。同样,如果我将UIImageView子类化并在intrinsicContentSize中返回显式大小,则没有问题。

我甚至在我的UIImageView子类中尝试了以下内容:

- (void) layoutSubviews {
    [super layoutSubviews];    
    self.intrinsicSizeForAutolayout = self.frame.size;    
    [super layoutSubviews];
}

- (CGSize)intrinsicContentSize {
    return self.intrinsicSizeForAutolayout;
}

其中 intrinsicSizeForAutolayout 是我为此目的定义的属性。我认为这可能与为preferredMaxLayoutWidth设置UILabel解决类似问题的方式类似。

但不是。它不起作用。

似乎我没有其他选择使用丑陋的屏幕宽度检查代码来根据屏幕宽度有条件地设置固定高度约束,这是我真正想要避免的,因为它有点挫败了使用自动布局的目的。第一名。

1 个答案:

答案 0 :(得分:7)

单元格contentView的宽度默认情况下没有任何约束(仅当将SDK添加到表视图时,其宽度由SDK设置),因此当您调用时systemLayoutSizeFittingSize:就此而言,约束求解器假设在尝试查找有效解决方案时,根据需要压缩宽度是有效的,这当然会导致错误的高度。

要解决此问题,您可以向contentView添加一个约束,将其宽度修复为最终的单元格/表格视图宽度。这是有效的,因为约束纳入单元格大小布局传递中,并导致systemLayoutSizeFittingSize:按预期工作。

使用PureLayout,我建议您执行以下操作:

[UIView autoSetPriority:UILayoutPriorityRequired - 1 forConstraints:^{
    [cell.contentView autoSetDimension:ALDimensionWidth toSize:CGRectGetWidth(tableView.bounds)];
}];

请注意,为约束设置小于Required的优先级并不是一个坏主意,只是因为这只是为了帮助调整大小操作,并且如果获得此异常,您不需要异常破坏(可能是未来的SDK视图单元格工作方式的变化)。但这可能并不重要。

此外,像往常一样,您可能希望确保此约束仅添加一次(并非每次调用tableView:heightForRowAtIndexPath:时) - 这应该很容易做到。

请参阅此处,了解示例项目分支的特定解决方案:https://gist.github.com/smileyborg/0a2082a4d26fcc7fde4d