iOS:以编程方式添加约束获取视图高度作为唯一指标

Posted

技术标签:

【中文标题】iOS:以编程方式添加约束获取视图高度作为唯一指标【英文标题】:iOS: Getting height of views with programatically added constraints as only indicator 【发布时间】:2014-10-08 15:43:41 【问题描述】:

各位 ios 程序员大家好。在创建应用程序时,我遇到了一个我似乎无法找到答案的问题。让我们整理一下:

我正在创建一个带有 UIScrollView 的 UIViewController,因为它是唯一的孩子。在这个视图里面我有一个 UIView,里面有一个 UIViews 列表,里面有 UILabel。众所周知,您需要为 UIScrollView 指定 contentSize。 问题是列表需要与它的内容是动态的,因此我无法事先知道视图高度。我正在添加所有具有约束的视图,其中高度设置为“> = 0”。 当我稍后尝试设置 UIScrollView 的高度时,我需要获取列表所在的 UIView 的高度,或者获取列表中最后一个视图的 origin.y 和高度。这当然需要在视图显示给用户之前准备好。

我目前试过view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize),返回0; view.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize),返回10000;和 view.origin.y + view.frame.height,它也返回 0。在我看来,约束还没有生效。

我尝试从 viewDidLoad() 设置约束和 UIScollView.contentSize。我还尝试在 viewDidLoad 中设置约束并在 viewWillAppear 中设置 contentSize;这产生了相同的结果。在 viewWillAppear 中设置约束和在 viewDidLoad 中设置 contentSize 只会导致崩溃。

底线:如果我想获取 view.height 或类似方法以返回正确的结果,我应该什么时候设置 UIScrollView.contentSize,同时准备好时间用户看到视图了吗?

顺便说一句,我正在用 Swift 制作这个应用程序,所以最好用这种语言回答,但我可以从 Objective-C 翻译成 Swift;以最适合您的方式发布。

谢谢! :)

【问题讨论】:

【参考方案1】:

你说:

众所周知,您需要为UIScrollView 指定contentSize

不,正如TN2154 所说,滚动视图与其子视图之间的约束被“解释为滚动视图的内容大小”(强调)。这是一个福音,因为如果进行自动布局,您不再需要使用contentSize。只需为滚动视图的子视图设置约束,内容大小就会自行处理。这利用了标签的固有大小(并确保标签的 numberOfLines 为零)。

唯一的技巧是它有时无法计算出标签的正确宽度(因为尾随约束是针对滚动视图的内容大小,它有时会使滚动视图成为水平滚动的)。您可以通过手动设置preferredMaxLayoutWidth 或通过在标签和滚动视图的超级视图之间设置宽度约束来解决此问题。

就个人而言,虽然我理解在滚动视图和标签之间添加 UIView 容器的倾向,但我建议您将它们丢失,除非您出于其他原因需要它们。恕我直言,它只会使约束不必要地复杂化。毛茸茸的就够了。显然,如果这些容器对您有其他用途,那么请继续保留它们(它们会正常工作),但如果您只是为了限制而这样做,您可能会考虑消除它们。

【讨论】:

您能否更深入地了解如何避免 UIScrollView 水平滚动?我试图为 UIViews 设置一个特定的宽度约束(它们是必要的),当这不起作用时,我尝试为 UILabels 设置 preferredMaxLayoutWidth。当这不起作用时,我尝试手动设置 sv.contentSize.width ,但这也没有效果。我究竟做错了什么?你能发布示例代码吗? 使用自动布局时,不要尝试手动设置framecontentSize。使用约束。要设置标签的宽度,可以使用preferredMaxLayoutWidth 或使用约束,就像我在下面所做的那样。仅供参考,虽然我通常在 IB 中这样做,但在代码中向您展示的唯一方法是以编程方式实现约束,我在这个演示中做了:gist.github.com/robertmryan/2211d9947b4ad6109659 在 IB 中更容易做到,但对我来说更难演示,比如我在上面的链接中做了。 或者,如果你太沉迷于此,打开translatesAutoresizingMaskIntoConstraints,你可以做所有老派的事情,玩宽度,手动计算高度等等。你似乎输了过程中有一点灵活性。 我已经以编程方式创建了所有约束,正如我所提到的,我一开始尝试不接触 frame 或 contentSize。这仍然没有成功。我真的更愿意避免打开 translatesAutoresizingMaskIntoConstraints,因为高度变化的文本长度会使这个过程变得困难和令人沮丧。顺便说一句,我不知道这是否重要,但我正在使用 constraintsWithVisualFormat。 经过 20 多个小时令人沮丧的工作后,我终于明白了为什么它对我不起作用。原来我忘了添加 |在视觉 y 约束结束时!它现在可以工作了,所以非常感谢你的帮助。 :D

以上是关于iOS:以编程方式添加约束获取视图高度作为唯一指标的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式将自动布局约束添加到恒定宽度和高度的子视图

Swift - StackView 和添加约束,以编程方式添加视图到堆栈 - 加载后调整单元格高度?

自动布局约束没有得到尊重

以编程方式添加前导/顶部约束

以编程方式更新约束 iOS

如何以编程方式设置滚动视图高度