我提出这个(有点)简单的问题只是为了挑剔一下,因为有时我担心我可能会滥用许多UIView的API,特别是在自动布局方面。
为了让它变得超级简单,我将以一个例子来说明,假设我需要一个UIView子类,它有一个图像图标和一个多行标签;我想要的行为是我的视图的高度随着标签的高度而改变(以适应文本内容),同时,我正在使用Interface Builder进行布局,所以我有以下内容:
其中包含一些约束条件,可为图像视图提供固定的宽度和高度,并为标签提供固定的宽度和位置(相对于图像视图):
现在,如果我向标签中添加一些文本,我希望该视图的高度会相应地调整以适当地适应文本,或者保持与xib中具有相同的高度。 在自动布局之前,我通常会执行以下操作:
在CustoView子类文件中,我会重写sizeThatFits:
如下:
- (CGSize) sizeThatFits:(CGSize)size{
//this stands for whichever method I would have used
//to calculate the height needed to display the text based on the font
CGSize labelSize = [self.titleLabel intrinsicContentSize];
//check if we're bigger than what's in ib, otherwise resize
CGFloat newHeight = (labelSize.height <= 21) ? 51: labelSize.height+20;
size.height = newHeight;
return size;
}
然后我会给它起个类似这样的名字:
myView.titleLabel.text = @"a big text to display that should be more than a line";
[myView sizeToFit];
现在,考虑到约束条件,我知道自动布局系统会调用视图树元素的 intrinsicContentSize
方法来确定它们的大小并进行计算。因此,我应该重写子视图中的 intrinsicContentSize
方法,返回与之前展示的 sizeThatFits:
方法完全相同的内容,唯一不同的是,在以前调用 sizeToFit
时,我的视图被正确调整大小,但是现在使用自动布局和 xib,这种方式行不通。
当然,我可以在我的子类中每次编辑文本时调用 sizeToFit
,并覆盖 intrinsicContentSize
方法,返回与 sizeThatFits:
完全相同的大小,但我认为这不是正确的方法。
我正在考虑覆盖 needsUpdateConstraints
和 updateConstraints
,但由于我的视图的宽度和高度是从 xib 中的自动调整掩码推断和翻译而来的,所以这还不太合理。
那么,你认为实现这里展示的内容,并完全支持自动布局的最简单和正确的方法是什么呢?
systemLayoutSizeFittingSize:…
方法的使用技巧很好,谢谢。UILabel 的preferredMaxLayoutWidth
有什么特别的问题吗?它可以自动调整大小以适应其他约束条件,对吧? - BenjohnpreferredMaxLayoutWidth
,以便intrinsicContentSize
返回使用换行的大小(我相信文本和preferredMaxLayoutWidth是唯一的内在内容)。我认为唯一自动设置它的方法是在某个地方重写layoutSubviews
并根据完成的布局值进行设置。相比之下,systemLayoutSizeFittingSize:
查看所有约束条件,而不仅仅是来自intrinsicContentSize的约束条件。因此,它将受到(1)影响宽度的其他约束条件的影响,以及(2)numberOfLines=0
和其参数targetSize
的组合的影响。 - algalUIStackView
使用intrinsicContentSize
来计算其子视图的大小,而不是使用sizeThatFits
等方法。这或多或少地迫使开发人员重写该方法并直接调用sizeThatFits
:/ - fatuhokuUIStackView
直接使用intrinsicContentSize
,我会感到非常惊讶。我期望它使用systemLayoutSizeFittingSize:
的短或长版本之一。如果是这种情况,那么只需建立适当的内部约束即可,而无需覆盖intrinsicContentSize
。我的理解是,拥有intrinsicContentSize
的唯一效果是导致系统自动生成某些不必要的约束,以表达首选大小。 - algalUILabel
一样实现intrinsicContentSize
。当混合使用自动布局和基于框架的手动布局时,你需要这样做。 - DawnSong