的开发者, 我在界面生成器(Xcode 5 / iOS 7)中的自动布局遇到了麻烦。 这是非常基础和重要的,所以我认为每个人都应该知道这是如何正确工作的。如果这是Xcode中的一个bug,那它就是一个严重的bug !

所以,每当我有这样的视图层次结构时,我就会遇到麻烦:

>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)

UIScrollView有固定的约束,例如,每边50px(没问题)。 然后我添加一个顶部空间约束UILabel(没有问题)(我甚至可以钉标签的高度/宽度,改变什么,但应该是不必要的,由于标签的内在大小)

当我给UILabel添加一个尾随约束时,问题就开始了:

例如,尾随空间到:Superview等于:25

现在出现了两个警告——我不明白为什么:

A)滚动内容大小不明确(滚动视图具有不明确的滚动内容高度/宽度)

B)视图错位(Label Expected: x= -67 Actual: x= 207)

我在一个新项目中做了这个最小的例子,你可以下载,我附上了一张截图。如你所见,Interface Builder期望Label位于UIScrollView的边界之外(橙色虚线矩形)。用解决问题工具更新标签的框架,将其移到那里。

请注意:如果你用一个UIView替换UIScrollView,行为是预期的(标签的帧是正确的,根据约束)。所以看起来要么是UIScrollView有问题,要么是我错过了一些重要的东西。

当我运行应用程序而不更新标签的框架时,它的位置很好,正是它应该在的地方,UIScrollView是可滚动的。 如果我确实更新了帧,标签就会从视野中消失,UIScrollView也不会滚动。

帮帮我,欧比王·克诺比!为什么是模棱两可的布局?为什么会出现这种错位的观点?

你可以在这里下载示例项目,试着看看你能弄清楚发生了什么: https://github.com/Wirsing84/AutoLayoutProblem


当前回答

对我来说,添加contentView并没有像建议的那样真正起作用。此外,由于添加了视图,它会产生开销(尽管我不认为这是一个大问题)。对我来说最有效的方法是关闭我的scrollView的歧义检查。一切都布置得很好,所以我认为在像我这样简单的情况下是可以的。但是请记住,如果你的scrollView的其他约束被打破,Interface-Builder将不再就此警告你。

其他回答

垂直滚动

添加一个带有约束0,0,0,0的UIScrollView到superview。 在ScrollView中添加一个UIView,约束为0,0,0,0到superview。 为UIScrollView添加相同宽度的约束。 添加高度到UIView。 向UIView添加带有约束的元素。 对于最靠近底部的元素,确保它有一个到UIView底部的约束。

[在XCode 7.2和iOS 9.2中测试]

对我来说,抑制Storyboard错误和警告的方法是将滚动视图和内容视图(在我的例子中,是一个stackview)的固有大小设置为Placeholder。这个设置可以在故事板的大小检查器中找到。它说-设置设计时间内在内容大小只影响在界面生成器中编辑时的视图。视图在运行时没有这个固有的内容大小。

所以,我想我们设置这个不会错。

注意:在storyboard中,我已经将scrollview的所有边固定在superview上,将stackview的所有边固定在scrollview上。在我的代码中,我已经为scrollview和stackview设置了translatesAutoresizingMaskIntoConstraints为false。我还没有提到内容大小。当堆栈视图动态增长时,在故事板中设置的约束确保堆栈是可滚动的。

故事板警告快把我逼疯了,我不想为了抑制警告而水平或垂直地将事物居中。

那些在uiscrollview而不是滚动中挣扎的人只是用你上一个视图的底部布局(在你的内容视图内部)来设置你的内容视图的底部约束。不要忘记删除中心Y的约束。

其余所有约束与上面定义的相同。Scrollview只关心从它的内容视图获取最大高度,我们将它设置为最后一个视图的底部约束,这意味着Scrollview将自动改变它的内容偏移量。

在我的例子中,最后一个视图是可用的,没有线属性= 0(自动调整它的高度取决于它的内容),所以它动态增加可用的高度,最终我们的可滚动区域增加,因为可用的底部布局与我们的内容视图的底部对齐,这迫使scrollview增加它的内容偏移。

Xcode 11+, Swift 5

如果你想知道为什么所有的答案都不再工作了,请确保你已经固定了内容视图(你已经放在滚动视图内的那个)到滚动视图的内容布局指南,而不是框架布局指南。

内容视图边缘(前导,后拉,顶部,底部)不应该像图像-框架布局指南上的前导那样被固定

但像这样-内容布局指南。

然后大部分答案都会适用于你。

现在最简单的方法是这样的:

把滚动视图放到根视图中 将滚动视图的所有边固定在父视图上 取另一个UIView(我们称之为content view)把它放到滚动视图中 将内容视图的所有边固定在滚动视图的内容布局指南上 固定内容视图的宽度等于滚动视图的框架布局指南 以任何你想要的方式固定内容视图的高度(我在下面的例子中使用了常量高度约束)

总的来说,在最简单的实现中,你的结构是这样的

Xcode 11 +。

使用自动布局的最简单方法:

Add UIScrollView and pin it 0,0,0,0 to superview (or your desired size) Add container of UIView type inside ScrollView, pin it 0,0,0,0 to all 4 sides and center it horizontally and vertically. In size inspector of container, change bottom and align center Y priority to 250. (for horizontal scroll change trailing and align center X) Add all views that you need into said container (UIView). Don't forget to set the bottom constraint on the lowest view. Select the UIScrollView, select the size inspector and deselect Content Layout Guides.