我问这个(不知何故)简单的问题只是为了挑剔,因为有时我担心我可能会滥用许多 UIView 的 API,尤其是在涉及自动布局时。
为了让它变得 super 简单,我举个例子,假设我需要一个 UIView 子类,它有一个图像图标和一个多行标签;我想要的行为是我的 View 的高度随着标签的高度而变化(以适应里面的文本),另外,我正在使用界面生成器进行布局,所以我有这样的东西:
具有一些约束,为 ImageView 提供固定的宽度和高度,并为标签提供固定的宽度和位置(相对于 ImageView ):
现在,如果我为标签设置了一些文本,我希望调整 View 的高度以适合它,或者保持它在 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];
现在,考虑到约束,我知道自动布局系统在 View 树元素上调用 intrinsicContentSize
以了解它们的大小并进行计算,因此我应该重写 intrinsicContentSize
在我的 subview 中返回与之前显示的 sizeThatFits:
方法中返回的完全相同的内容,除了以前在调用 sizeToFit
时我的 View 正确调整大小,但现在使用自动布局,结合 xib,这不会发生。
当然,每次我在我的子类中编辑文本时,我可能都会调用 sizeToFit
,以及一个重写的 intrinsicContentSize
,它返回与 sizeThatFits 完全相同的大小:
,但不知何故,我认为这不是正确的做法。
我正在考虑覆盖 needsUpdateConstraints
和 updateConstraints
,但仍然没有多大意义,因为我的 View 的宽度和高度是从 xib 的自动调整掩码推断和转换的。
这么久了,您认为最干净、最正确的方法是什么,可以准确地制作我在这里展示的内容并支持完全自动布局?
最佳答案
我认为您不需要定义intrinsicContentSize。
有两个理由认为:
当 Auto Layout 文档讨论
intrinsicContentSize
时,它将其称为与“叶 subview ”相关的按钮或标签,其中大小可以完全根据其内容计算。这个想法是它们是 View 层次结构树中的叶子,而不是分支,因为它们不是由其他 View 组成的。IntrinsicContentSize 并不是自动布局中的“基本”概念。基本概念只是约束和由约束绑定(bind)的属性。 intrinsicContentSize、内容拥抱优先级和抗压缩优先级实际上只是用于生成有关大小的内部约束的便利。最终大小只是这些约束以通常方式与所有其他约束交互的结果。
那又怎样?因此,如果您的“自定义 View ”实际上只是几个其他 View 的组合,那么您不需要定义intrinsicContentSize。您可以只定义创建所需布局的约束,这些约束也会产生您想要的大小。
在您描述的特定情况下,我会设置从标签到 super View 的 >=0 底部空间约束,从图像到 super View 的另一个约束,然后还有一个 低优先级 整个 View 的高度为零的约束。低优先级约束将尝试缩小程序集,而其他约束阻止它缩小到剪裁其 subview 的程度。
如果您从不明确定义intrinsicContentSize,您如何看待这些约束产生的大小?一种方法是强制布局,然后观察结果。
另一种方法是使用 systemLayoutSizeFittingSize:
(在 iOS8 中,鲜为人知的 systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:
)。这与 sizeThatFits:
比 intrinsicContentSize
更接近。系统将使用它来计算 View 的适当大小,同时考虑到它包含的所有约束,包括内在的内容大小约束以及所有其他约束。
不幸的是,如果您有一个多行标签,您可能还需要配置 preferredMaxLayoutWidth
以获得良好的结果,但这是另一回事...
关于ios - 正确使用 intrinsicContentSize 和 sizeThatFits : on UIView Subclass with autolayout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24127032/