Автоматическая установка высоты представления контейнера на основе подвидов

Я знаю, что этот вопрос задавался много раз, но я не могу понять суть этой проблемы.

Используя Auto Layout, я хотел бы автоматически установить высоту моего контейнера UIView на основе его подвидов. Я рассмотрел использование sizeToFit и других различных методов суммирования высоты моих подпредставлений, однако из того, что я прочитал, высота моего контейнера должна быть автоматической при использовании автоматического макета из-за «внутреннего» размера содержимого подпредставлений.

Ниже приведен уменьшенный случай того, что я испытываю. Я был бы очень признателен за любое руководство!

Обзор:

  1. Создайте контейнер UIView, прикрепите к левой и правой сторонам супервизора, без явной высоты, выровняйте его центр Y с его центром супервизора Y
  2. Создайте UIView шириной 300 и высотой 100, добавьте его как подпредставление в представление контейнера, выровняйте его centerX с centerX представления контейнера, прикрепите к верхнему краю представления контейнера.
  3. Повторите шаг № 2, но на этот раз прикрепите его верхнюю часть к нижнему краю № 2.
  4. Ожидаемая высота представления контейнера равна 200, за исключением того, что его высота на самом деле по-прежнему равна 0 (поэтому выравнивание по центру Y отключено).

Визуализация проблемы

Код:

class ViewController: UIViewController {

    let redView = RedView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(redView)
        view.setNeedsUpdateConstraints()
    }

}

class RedView: UIView {

    let greenView = GreenView()
    let blueView = BlueView()

    init() {
        super.init(frame: CGRect.zero)

        translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = UIColor.red()

        addSubview(greenView)
        addSubview(blueView)
        setNeedsUpdateConstraints()
    }

    override func updateConstraints() {
        super.updateConstraints()

        NSLayoutConstraint(item: greenView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: blueView, attribute: .top, relatedBy: .equal, toItem: greenView, attribute: .bottom, multiplier: 1, constant: 0).isActive = true

        NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: superview, attribute: .left, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: superview, attribute: .right, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: superview, attribute: .centerY, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200).isActive = true
    }

}

class GreenView: UIView {

    init() {
        super.init(frame: CGRect.zero)

        translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = UIColor.green()
    }

    override func updateConstraints() {
        super.updateConstraints()

        NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300).isActive = true
        NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100).isActive = true
        NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: superview, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
    }

}

class BlueView: UIView {

    init() {
        super.init(frame: CGRect.zero)

        translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = UIColor.blue()
    }

    override func updateConstraints() {
        super.updateConstraints()

        NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300).isActive = true
        NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100).isActive = true
        NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: superview, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
    }

}

person Jody Heavener    schedule 22.08.2016    source источник
comment
Не по теме: мне не нравится, как RedView добавляет ограничения в супервизор. Гораздо проще, если только родительское представление знает, как размещать свои подпредставления. В вашем случае ViewController добавит ограничение в RedView сразу после вызова view.addSubview(redView).   -  person chuthan20    schedule 23.08.2016


Ответы (1)


Вам нужно прикрепить низ blueView к низу redView, просто добавьте эту строку в updateConstraints redView:

NSLayoutConstraint(item: blueView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0).active = true
person Eric Qian    schedule 23.08.2016
comment
Ааа имеет смысл. Спасибо! - person Jody Heavener; 23.08.2016
comment
@EricQian, не могли бы вы проверить мою проблему, братан stackoverflow.com/questions/45690065/ ? - person May Phyu; 16.08.2017