【问题标题】:How to center two views in super view with greater than or equal to constraints如何在大于或等于约束的超级视图中居中两个视图
【发布时间】:2020-02-24 19:15:59
【问题描述】:

我制作了一个带有两个标签的示例 ViewController 来突出我的问题。目标是将标签垂直分隔 10,然后使用大于或等于约束将它们垂直居中。我使用的是视觉格式,但是如果我设置了像view.topAnchor.constraint(greaterThan... 这样的约束,这应该适用。我也有两个限制来水平布局标签

我的视图控制器:

class myVC: UIViewController {
    lazy var titleLabel: UILabel = {
        let l = UILabel(frame: .zero)
        l.translatesAutoresizingMaskIntoConstraints = false
        l.text = "Hello World"
        l.font = .systemFont(ofSize: 50)
        l.textColor = .black
        return l
    }()

    lazy var descLabel: UILabel = {
        let l = UILabel(frame: .zero)
        l.translatesAutoresizingMaskIntoConstraints = false
        l.text = "description"
        l.font = .systemFont(ofSize: 35)
        l.textColor = .gray
        return l
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .yellow
        view.addSubview(titleLabel)
        view.addSubview(descLabel)
        titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        descLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor).isActive = true
        NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(<=50)-[titleLabel]-(10)-[descLabel]-(<=50)-|", options: .init(), metrics: nil, views: ["titleLabel": titleLabel, "descLabel": descLabel]))
    }

}

这导致。据我了解,这应该将视图分隔 10 pts,并将标签垂直居中,因为在 "V:|-(&lt;=50)-[titleLabel]-(10)-[descLabel]-(&lt;=50)-|" 格式中,我说标题标签的顶部和超级视图的顶部之间的距离至少应为 (greaterThanOrEqualTo) 50,并且描述标签底部和超级视图底部之间的距离至少应为 50。如果我想将两个标签垂直居中,我的顶部和底部约束应该是什么样的?

是的,我意识到我可以设置垂直和水平中心,但这是我为一个我无法使用它们的问题制作的示例。我需要能够以大于(或小于)或等于约束的方式使视图居中。

【问题讨论】:

  • 仅使用两个标签将很难实现。不过,通过将它们嵌入UIView(并将视图垂直居中)或使用UIStackView 更容易做到这一点
  • 在我的实际应用程序中,我有多个视图的垂直堆栈,它们之间的间距不一致,所以 stackView 并没有真正帮助我。
  • 您可以在堆栈视图中嵌入堆栈视图。否则,将标签嵌入UIView。但是...尝试使用 VFL(视觉格式语言)将元素居中是有问题的。

标签: ios swift autolayout constraints visual-format-language


【解决方案1】:

使用 VFL 使元素居中非常困难。

除非它们嵌入在 UIViewUIStackView 中,否则将两个元素居中也很困难。

这是将标签嵌入“容器”UIView 的一种选择:

class MyVC: UIViewController {
    lazy var titleLabel: UILabel = {
        let l = UILabel(frame: .zero)
        l.translatesAutoresizingMaskIntoConstraints = false
        l.text = "Hello World"
        l.font = .systemFont(ofSize: 50)
        l.textColor = .black

        // center the text in the label - change to .left if desired
        l.textAlignment = .center

        return l
    }()

    lazy var descLabel: UILabel = {
        let l = UILabel(frame: .zero)
        l.translatesAutoresizingMaskIntoConstraints = false
        l.text = "description"
        l.font = .systemFont(ofSize: 35)
        l.textColor = .gray

        // center the text in the label - change to .left if desired
        l.textAlignment = .center

        return l
    }()

    lazy var containerView: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .yellow

        // give the labels and containerView background colors to make it easy to see the layout
        titleLabel.backgroundColor = .green
        descLabel.backgroundColor = .cyan
        containerView.backgroundColor = .blue

        // add containerView to view
        view.addSubview(containerView)

        // add labels to containerView
        containerView.addSubview(titleLabel)
        containerView.addSubview(descLabel)

        NSLayoutConstraint.activate([

            // constrain titleLabel Top to containerView Top
            titleLabel.topAnchor.constraint(equalTo: containerView.topAnchor),

            // constrain titleLabel Leading and Trailing to containerView Leading and Trailing
            titleLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            titleLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),

            // constrain descLabel Leading and Trailing to containerView Leading and Trailing
            descLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            descLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),

            // constrain descLabel Bottom to containerView Bottom
            descLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),

            // constrain descLabel Top 10-pts from titleLabel Bottom
            descLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 10.0),

            // constrain containerView centered horizontally and vertically
            containerView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            containerView.centerYAnchor.constraint(equalTo: view.centerYAnchor),

        ])

    }

}

结果:

【讨论】:

    【解决方案2】:

    这可以通过使用 stackview 轻松实现。在 stackview 中添加两个标签,并将其与所有其他约束(顶部、前导、底部、尾随)在超级视图中垂直居中。 这是您的用例的视图控制器示例代码。

    class ViewController: UIViewController {
    
        lazy var titleLabel: UILabel = {
            let label = UILabel()
            label.translatesAutoresizingMaskIntoConstraints = false
            label.text = "Hello \nWorld"
            label.font = .systemFont(ofSize: 50)
            label.backgroundColor = .orange
            label.numberOfLines = 0
            label.textColor = .black
            return label
        }()
    
        lazy var descLabel: UILabel = {
            let label = UILabel()
            label.translatesAutoresizingMaskIntoConstraints = false
            label.text = "a\n b\n c\n"
            label.font = .systemFont(ofSize: 35)
            label.backgroundColor = .green
            label.numberOfLines = 0
            label.textColor = .gray
            return label
        }()
    
        lazy var contentView: UIStackView = {
            let stackView = UIStackView()
            stackView.axis = .vertical
            stackView.translatesAutoresizingMaskIntoConstraints = false
            stackView.spacing = 10
            stackView.distribution = .fill
            return stackView
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.view.backgroundColor = UIColor.white
    
            contentView.addArrangedSubview(titleLabel)
            contentView.addArrangedSubview(descLabel)
            self.view.addSubview(contentView)
    
            let constraints = [
                contentView.topAnchor.constraint(greaterThanOrEqualTo: view.safeAreaLayoutGuide.topAnchor),
                contentView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
                contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                contentView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                contentView.bottomAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.bottomAnchor)
            ]
            NSLayoutConstraint.activate(constraints)
    
        }
    }
    

    上面的代码会产生这个视图,它会继续占据顶部和底部的空间,直到遇到安全区域。此外,您可以设置垂直内容拥抱和抗压优先级来控制哪个标签扩大或缩小。

    【讨论】:

      猜你喜欢
      • 2019-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多