Noo*_*dew 3 constraints uiscrollview ios autolayout swift
我有一个UIViewController? SingleEventController显示事件。因为它有动态信息要显示,所以我选择创建一个新类UIScrollView EventScrollView。我试图基于这个很好解释的答案来意识到这一点
。
我尝试应用纯自动布局方法:在其中创建另一个UIView contentView,其中包含所有信息并锚定到 scrollView 的所有四个锚点。
scrollView 的 contentSize 是在 SingleEventController 的viewDidLayoutSubviews函数中确定的。
我的挣扎是,rightAnchor 似乎有问题。所有的信息元素都超过了视图的边界,较大的自动换行UILabels不起作用,并且在正确的锚点处布置的每个项目都消失了。(例如,作为 contentView 子视图的UITableView nopePeopleTV 中的用户名。)
SingleEventController中的代码:
view.addSubview(scrollView)
scrollView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: buttonViewDividerView.topAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
override func viewDidLayoutSubviews() {
let heightOfAllObjects = scrollView.calculateHeightOfAllObjects()
scrollView.contentSize = CGSize(width: self.view.frame.width, height: heightOfAllObjects + scrollView.heightOfAllPaddings)
}
Run Code Online (Sandbox Code Playgroud)
EventScrollView 中的代码:
addSubview(contentView)
contentView.addSubview(titleLabel)
contentView.addSubview(locationLabel)
...
contentView.addSubview(nopePeopleTV)
contentView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
titleLabel.anchor(top: contentView.topAnchor, left: contentView.leftAnchor, bottom: nil, right: contentView.rightAnchor, paddingTop: 10, paddingLeft: padding, paddingBottom: 0, paddingRight: padding, width: 0, height: 0)
locationLabel.anchor(top: titleLabel.bottomAnchor, left: contentView.leftAnchor, bottom: nil, right: nil, paddingTop: 0, paddingLeft: padding, paddingBottom: 0, paddingRight: 0, width: 200, height: 0)
nopePeopleTV.anchor(top: maybePeopleTV.bottomAnchor, left: contentView.leftAnchor, bottom: nil, right: contentView.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
layoutIfNeeded()
contentView.layoutIfNeeded()
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
我的锚函数如下所示:
func anchor(top: NSLayoutYAxisAnchor?, left: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, right: NSLayoutXAxisAnchor?, paddingTop: CGFloat, paddingLeft: CGFloat, paddingBottom: CGFloat, paddingRight: CGFloat, width: CGFloat, height: CGFloat) {
translatesAutoresizingMaskIntoConstraints = false
if let top = top {
topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
}
if let left = left {
leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
}
if let right = right {
rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
}
if width != 0 {
widthAnchor.constraint(equalToConstant: width).isActive = true
}
if height != 0 {
heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
Run Code Online (Sandbox Code Playgroud)
问题是您让内容视图宽度由子视图的宽度从内向外决定。您需要为内容视图提供与滚动视图本身的宽度相匹配的宽度约束。
我将用一个人工但完整的纯代码示例来演示差异:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let sv = UIScrollView()
sv.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(sv)
NSLayoutConstraint.activate([
sv.topAnchor.constraint(equalTo: self.view.topAnchor),
sv.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
sv.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
sv.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
])
let cv = UIView() // content view
cv.translatesAutoresizingMaskIntoConstraints = false
sv.addSubview(cv)
NSLayoutConstraint.activate([
sv.topAnchor.constraint(equalTo: cv.topAnchor),
sv.leadingAnchor.constraint(equalTo: cv.leadingAnchor),
sv.trailingAnchor.constraint(equalTo: cv.trailingAnchor),
sv.bottomAnchor.constraint(equalTo: cv.bottomAnchor),
])
let lab = UILabel()
lab.translatesAutoresizingMaskIntoConstraints = false
lab.numberOfLines = 0
lab.text = Array(repeating: "xxx", count: 100).joined(separator: " ")
cv.addSubview(lab)
NSLayoutConstraint.activate([
lab.topAnchor.constraint(equalTo: cv.topAnchor, constant:30),
lab.leadingAnchor.constraint(equalTo: cv.leadingAnchor),
lab.trailingAnchor.constraint(equalTo: cv.trailingAnchor),
])
}
}
Run Code Online (Sandbox Code Playgroud)
结果如下:
我们有一个很长的标签,但它没有环绕:它一直向右延伸,离开屏幕。那是因为内容视图本身的右边缘离开了屏幕。那是因为我们没有采取任何措施来防止这种情况发生。长标签本身使内容视图与标签的整个文本一样宽。
现在我将最后一行代码添加到viewDidLoad:
cv.widthAnchor.constraint(
equalTo:sv.frameLayoutGuide.widthAnchor).isActive = true
Run Code Online (Sandbox Code Playgroud)
结果是这样的:
内容视图现在是滚动视图的宽度,因此标签环绕在滚动视图中。
然而,我们不会对内容视图的高度做同样的事情;我们希望它根据它的子视图垂直增长。这样,我们将能够垂直滚动(这是您想要的)而不是水平滚动(这也是您想要的)。