斯威夫特:我无法使自动布局约束适用于我的 UIScrollView
Posted
技术标签:
【中文标题】斯威夫特:我无法使自动布局约束适用于我的 UIScrollView【英文标题】:Swift: I'm not able to make autolayout constraints work for my UIScrollView 【发布时间】:2017-06-08 10:03:45 【问题描述】:我正在尝试制作一个简单的布局,当视图太多而无法在屏幕上显示时,它应该垂直滚动。
这就是我目前所拥有的:
我创建了一个滚动视图和一个类似的容器视图
let mainScrollView: UIScrollView =
let scrollView = UIScrollView()
scrollView.isUserInteractionEnabled = true
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
()
let containerView: UIView =
let view = UIView()
view.backgroundColor = .lightGray
view.translatesAutoresizingMaskIntoConstraints = false
return view
()
然后我将滚动视图添加到主视图,将容器视图添加到滚动视图,并将几个标签添加到容器视图
view.addSubview(mainScrollView)
mainScrollView.addSubview(containerView)
containerView.addSubview(firstLabel)
containerView.addSubview(secondLabel)
我将滚动视图固定到主视图,将容器视图固定到滚动视图。之后我开始像这样在容器视图中添加标签
mainScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
mainScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
mainScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
mainScrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
containerView.topAnchor.constraint(equalTo: mainScrollView.layoutMarginsGuide.topAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: mainScrollView.layoutMarginsGuide.bottomAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
firstLabel.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
firstLabel.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 30).isActive = true
firstLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true
firstLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
secondLabel.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
secondLabel.topAnchor.constraint(equalTo: firstLabel.bottomAnchor, constant: 750).isActive = true
secondLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true
secondLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
问题是由于某种原因,滚动视图无法计算它的高度并且它不会垂直滚动。第二个标签仍然不可见,因为它在屏幕上太“低”了。
我尝试将容器视图的底部约束设置为第二个标签的底部,但老实说我无处可去。
我错过了什么?如何设置约束以使滚动视图使用自动布局滚动(不设置容器视图的特定高度)?
【问题讨论】:
【参考方案1】:Scrollview 向任一方向滚动。因此,添加到其中的任何视图都需要一些额外的约束来让 Scrollview 计算其内容大小。
您已将容器视图固定到滚动视图。如果您正在查看像表格视图这样的垂直滚动视图,那么您还需要将滚动的宽度设置为容器视图,以便它可以计算宽度。
接下来是高度,它会根据容器视图中添加的 UI 元素自动计算。确保所有标签在容器视图和容器视图顶部都具有前导、尾随和垂直间距。这将使滚动视图知道所需的高度。
self.scrollView.translatesAutoresizingMaskIntoConstraints = false
self.contentView.translatesAutoresizingMaskIntoConstraints = false
self.label1.translatesAutoresizingMaskIntoConstraints = false
self.label2.translatesAutoresizingMaskIntoConstraints = false
self.label3.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(self.label1)
self.contentView.addSubview(self.label2)
self.contentView.addSubview(self.label3)
self.scrollView.addSubview(self.contentView)
self.view.addSubview(self.scrollView)
NSLayoutConstraint.activate([
self.scrollView.topAnchor.constraint(equalTo: self.view.topAnchor),
self.scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
self.scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor)
])
NSLayoutConstraint.activate([
self.contentView.topAnchor.constraint(equalTo: self.scrollView.topAnchor),
self.contentView.trailingAnchor.constraint(equalTo: self.scrollView.trailingAnchor),
self.contentView.bottomAnchor.constraint(equalTo: self.scrollView.bottomAnchor),
self.contentView.leadingAnchor.constraint(equalTo: self.scrollView.leadingAnchor),
self.contentView.widthAnchor.constraint(equalTo: self.scrollView.widthAnchor)
])
NSLayoutConstraint.activate([
self.label1.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor),
self.label2.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor),
self.label3.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor),
self.label1.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor),
self.label2.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor),
self.label3.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor)
])
NSLayoutConstraint.activate([
self.label1.topAnchor.constraint(equalTo: self.contentView.topAnchor),
self.label2.topAnchor.constraint(equalTo: self.label1.bottomAnchor),
self.label3.topAnchor.constraint(equalTo: self.label2.bottomAnchor),
self.label3.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor)
])
并且在运行时,它也不会抱怨任何约束问题。水平滚动也可以这样做。
【讨论】:
非常感谢,您给了我正确的提示,我解决了问题。我提交了一个答案,以供将来可能会发现此问题的读者参考。 @Luca 没问题!即将用代码更新。 :) 也请查看NSLayoutConstraint.activate([])
。我发现这很方便。
哇,真的好用!肯定会用,谢谢建议【参考方案2】:
非常感谢@GoodSp33d,你为我指明了正确的方向。
我像你说的那样添加了宽度约束:
containerView.widthAnchor.constraint(equalTo: mainScrollView.widthAnchor).isActive = true
而且关键还是要更新底部约束:
containerView.bottomAnchor.constraint(equalTo: secondLabel.bottomAnchor).isActive = true
这是完整的工作代码:
mainScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
mainScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
mainScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
mainScrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
containerView.topAnchor.constraint(equalTo: mainScrollView.topAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo: mainScrollView.trailingAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: mainScrollView.bottomAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo: mainScrollView.leadingAnchor).isActive = true
containerView.widthAnchor.constraint(equalTo: mainScrollView.widthAnchor).isActive = true
firstLabel.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
firstLabel.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 30).isActive = true
firstLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true
firstLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
secondLabel.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
secondLabel.topAnchor.constraint(equalTo: firstLabel.bottomAnchor, constant: 550).isActive = true
secondLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true
secondLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
containerView.bottomAnchor.constraint(equalTo: secondLabel.bottomAnchor).isActive = true
感谢您的帮助。
【讨论】:
以上是关于斯威夫特:我无法使自动布局约束适用于我的 UIScrollView的主要内容,如果未能解决你的问题,请参考以下文章