0

我一直在关注 Paul Hudsons 的 Hacking with Swift 教程,我正在完成项目 6,他以编程方式使用布局约束。我一直在仅使用 Interface Builder 完成此类任务,但我很想学习如何以编程方式完成它。

在他的教程中,我们有以下代码将 5 个 UILabel 添加到主控制器的视图中。

        let label1 = UILabel()
        label1.translatesAutoresizingMaskIntoConstraints = false
        label1.text = "THESE"
        label1.backgroundColor = #colorLiteral(red: 0.5725490451, green: 0, blue: 0.2313725501, alpha: 1)
        label1.sizeToFit()

// do the same with label2, label3, label4, label5
        
        view.addSubview(label1)
        view.addSubview(label2)
        view.addSubview(label3)
        view.addSubview(label4)
        view.addSubview(label5)

然后我可以手动添加约束:

        let dictionary = [
            "label1": label1,
            "label2": label2,
            "label3": label3,
            "label4": label4,
            "label5": label5
        ]

        let metrics=[ "labelHeight":80]

        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[label1(labelHeight@999)]-[label2(label1)]-[label3(label1)]-[label4(label1)]-[label5(label1)]-(>=10)-|", options: [], metrics: metrics, views: dictionary))

        for label in dictionary.keys {
            view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[\(label)]|", options: [], metrics:nil, views: dictionary))
        }

如您所见,我将第一个标签的高度设置为 80。然后将 label1 的优先级设置为 999,并使其余标签遵循 label1 的高度约束。

这在纵向和横向模式下都可以正常工作。

人像模式1 横向模式 1

现在我将代码转换为使用锚。

   let heightConstraint = label1.heightAnchor.constraint(equalToConstant: 88)
        heightConstraint.priority = UILayoutPriority(rawValue: 999)
        heightConstraint.isActive = true

        for label in [label2, label3, label4, label5] {
            label.heightAnchor.constraint(equalTo: label1.heightAnchor, multiplier: 1).isActive = true
        }

        var previousLabel : UILabel?
        for label in [label1, label2, label3, label4, label5] {
            label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
            label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true

            if let previousLabel = previousLabel {
                label.topAnchor.constraint(equalTo: previousLabel.bottomAnchor, constant: 10).isActive = true
            } else {
                label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
            }
            previousLabel = label
        }
        label5.bottomAnchor.constraint(greaterThanOrEqualTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 10.0).isActive = true

我想我在这里遗漏了一些东西,因为

  1. 当应用程序处于纵向模式时,它会尝试填满整个屏幕
  2. 当应用程序处于横向模式时,label5 被切断。

人像模式 2 横向模式 2

我想我在使用锚点时在这里遗漏了一些东西?我猜是这个:

-(>=10)-

但我不确定如何使用锚模式来做到这一点。任何帮助将不胜感激!

4

1 回答 1

1

对于 label5,您应该将底部约束更改为:

label5.bottomAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10.0).isActive = true

它应该是一个负数,因为您将其固定到下方的锚点(与之前的锚点相比,您将其固定到当前锚点上方的标签)。对于负数,您需要使用lessThanOrEqualTo.

对于垂直布局,它也可以正常工作,因为约束是lessThanOrEqualTo

于 2021-09-04T11:47:55.823 回答