Как центрировать два вида в суперпредставлении с ограничениями, большими или равными - PullRequest
0 голосов
/ 24 февраля 2020

Я сделал пример ViewController с двумя метками, чтобы выделить мою проблему. Цель состоит в том, чтобы вертикально разделить метки на 10, а затем отцентрировать их по вертикали, используя ограничения, превышающие или равные. Я использую визуальный формат, но это должно применяться, если я устанавливаю свои ограничения как view.topAnchor.constraint(greaterThan.... У меня также есть два ограничения для горизонтального размещения меток

Мой ViewController:

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]))
    }

}

Это приводит к wrong constraints. Насколько я понимаю, это ДОЛЖНО разделять виды на 10 пунктов и центрировать метки по вертикали, потому что в формате "V:|-(<=50)-[titleLabel]-(10)-[descLabel]-(<=50)-|" я говорю, что расстояние между вершиной метки заголовка и вершиной супервизора должно быть не менее 50 (большеThanOrEqualTo) и расстояние между нижней частью описания и нижней частью superView должно быть не менее 50. Как должны выглядеть мои ограничения сверху и снизу, если я хочу центрировать две метки по вертикали?

Да, я понимаю, что могу просто установить вертикальную и горизонтальные центры, но это пример, который я сделал для проблемы, для которой я не могу их использовать. Мне нужно иметь возможность центрировать вид с большим (или меньшим) ограничением или равным ему.

Ответы [ 2 ]

1 голос
/ 24 февраля 2020

Очень сложно центрировать элементы с помощью VFL.

Также трудно центрировать два элемента, если они не встроены в UIView или UIStackView.

. Вот один из вариантов, встраивая метки в "контейнер" 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),

        ])

    }

}

Результат:

enter image description here

0 голосов
/ 24 февраля 2020

Этого можно легко достичь с помощью стека. Добавьте обе метки в виде стека и отцентрируйте его вертикально в суперпредставлении со всеми другими ограничениями (верхний, ведущий, нижний, конечный). Вот пример кода контроллера представления для вашего варианта использования.

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)

    }
}

Приведенный выше код приведет к этому представлению, и он продолжит занимать верхнее и нижнее пространство, пока не встретит safeArea. Кроме того, вы можете установить приоритет вертикальной ориентации содержимого и сопротивления сжатию, чтобы указать, какую метку расширять или сжимать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...