【问题标题】:Swift: I'm not able to make autolayout constraints work for my UIScrollView斯威夫特:我无法使自动布局约束适用于我的 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

问题是由于某种原因,滚动视图无法计算它的高度并且它不会垂直滚动。第二个标签仍然不可见,因为它在屏幕上太“低”了。

我尝试将容器视图的底部约束设置为第二个标签的底部,但老实说我无处可去。

我错过了什么?如何设置约束以使滚动视图使用自动布局滚动(不设置容器视图的特定高度)?

【问题讨论】:

    标签: ios swift uiscrollview autolayout


    【解决方案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
    

    感谢您的帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-06
      • 1970-01-01
      • 2022-06-17
      • 2023-02-23
      • 2012-11-10
      • 2014-12-29
      相关资源
      最近更新 更多