在 iOS 11 及更高版本中,滚动视图有两组布局指南,一组用于可滚动内容,contentLayoutGuide(指示滚动行为),另一组用于其框架,frameLayoutGuide(指示大小子视图)。
例如,这添加了一个子视图,它一直插入 20 个点,其宽度是相对于滚动视图的框架设置的,但具有固定的高度:
let subview = UIView()
subview.translatesAutoresizingMaskIntoConstraints = false
subview.backgroundColor = .red
scrollView.addSubview(subview)
NSLayoutConstraint.activate([
subview.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor, constant: 20),
subview.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor, constant: -20),
subview.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor, constant: 20),
subview.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor, constant: -20),
subview.heightAnchor.constraint(equalToConstant: 1000),
subview.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor, constant: -40),
])
您也可以在 IB 中执行此操作,完全无需任何编码:
在 iOS 11 之前,在没有 frameLayoutGuide 的情况下,您必须根据滚动视图的父视图设置子视图的约束,我将在下面概述该过程。但是从 iOS 11 开始,以上是更直观的解决方案。
您在问题中描述的约束等同于以下 VFL:
-
滚动视图占据整个视图
H:|[scrollView]|
V:|[scrollView]|
-
红色视图高 60 pt,与滚动视图的 contentSize 边缘有 15 的边距:
H:|-(15)-[redView]-(15)-|
V:|-(15)-[redView(60)]-(15)-|
红色视图是模棱两可的,因为没有定义它的宽度。 (红色视图和滚动视图之间的水平约束定义滚动视图的contentSize,而不是红色视图的宽度。参见Apple Technical Note 2154。)
您可以通过添加一个约束来解决这种歧义,即红色视图比主视图窄 30pt。因此,通过 control 在红色视图和滚动视图的超级视图之间添加约束 - 从红色视图拖动到滚动视图(这可能是从文档大纲中最容易做到的):
然后选择“等宽”:
已将红色视图定义为与主视图相同的宽度,您现在必须更改该约束以修改常量以调整您在红色视图和滚动视图的contentSize 之间提供的边距。因此,选择您刚刚添加的约束并对其进行编辑,将常量更改为 -30:
坦率地说,Interface Builder 技术有点麻烦。以编程方式说明如何执行此操作可能更容易:
view.addConstraint(NSLayoutConstraint(item: redView, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1.0, constant: -30))