IOS 横向屏幕的 SafeAreaLayoutGuide 锚点

IOS SafeAreaLayoutGuide anchor for landscape screen

我一直在关注 Paul Hudsons 的 Hacking 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。然后将标签 1 的优先级设置为 999,并使其余标签遵循标签 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 被切断。

我想我在使用锚点时遗漏了什么?我猜是这样的:

-(>=10)-

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

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

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

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

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