Программно создавая ограничения, связанные с просмотром полей контроллера
Я пытаюсь сделать вид, который будет действовать как своего рода "панель", прикрепленная к правой стороне контроллера вида.
То есть он связан с конечным, верхним и нижним полями родительского контроллера представления со статической шириной 300
Тем не менее, я просто не могу понять это правильно, я либо нарушаю ограничение, либо делаю что-то, что xcode говорит мне, что это незаконно.
Что я делаю неправильно?
Вот код в контроллере
let myView = UIView()
view.backgroundColor = UIColor.redColor()
self.view.addSubview(view)
let topConstraint = NSLayoutConstraint(item: myView,
attribute: .Top,
relatedBy: .Equal,
toItem: self.topLayoutGuide,
attribute: .Bottom,
multiplier: 1,
constant: 0)
let trailingConstraint = NSLayoutConstraint(item: self.view,
attribute: .TrailingMargin,
relatedBy: .Equal,
toItem: myView,
attribute: .Trailing,
multiplier: 1,
constant: 0)
let bottomConstraint = NSLayoutConstraint(item: self.bottomLayoutGuide,
attribute: .Top,
relatedBy: .Equal,
toItem: myView,
attribute: .Bottom,
multiplier: 1,
constant: 0)
let widthConstraint = NSLayoutConstraint(item: myView,
attribute: .Width,
relatedBy: .Equal,
toItem: nil,
attribute: .NotAnAttribute,
multiplier: 1,
constant: 300)
self.view.addConstraints([trailingConstraint])
view.addConstraints([topConstraint, bottomConstraint, widthConstraint])
3 ответа
На самом деле проблема в вашем коде в том, что вы не установили translatesAutoresizingMaskIntoConstraints
из myview
в false
всякий раз, когда вы хотите использовать ограничения автоматического размещения, вы должны установить translatesAutoresizingMaskIntoConstraints
зрения ложного. Другая проблема в том, что вы не добавляете myview
на self.view я обновил ваш код и он работает нормально в соответствии с вашими ограничениями.
Поместите ниже код в вашем ViewController .
let myView = UIView()
myView.backgroundColor = UIColor.redColor()
self.view.addSubview(myView)
myView.translatesAutoresizingMaskIntoConstraints = false
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Bottom, relatedBy: .Equal, toItem: self.bottomLayoutGuide, attribute:.Top, multiplier: 1, constant: 20))
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute,multiplier: 1, constant: 300))
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .TrailingMargin, relatedBy: .Equal, toItem: view, attribute: .TrailingMargin, multiplier: 1, constant: 0))
В приведенном выше примере кода кажется, что вы путаете view
а также myView
в нескольких местах. В любом случае, widthConstraint
должны быть добавлены к myView
а также topConstraint
, trailingConstraint
, а также bottomConstraint
должны быть добавлены к self.view
, Причина этого заключается в том, что ограничения должны быть добавлены к ближайшему предку суперпредставления, в котором изложены оба представления, вовлеченные в ограничение. В случае, когда вы ограничиваете атрибут дочернего представления атрибутом в его родительском представлении, ограничение должно быть добавлено к родительскому представлению, поскольку оно размещает и себя, и дочернее представление. Если у вас есть ограничение между двумя одноуровневыми представлениями, то ограничение будет добавлено к их родительскому представлению, поскольку именно ближайший предок размещает оба задействованных представления.
Если вы можете использовать iOS 9.0 и выше, гораздо проще и проще использовать новые NSLayoutAnchor и NSLayoutDimension API для создания подобных ограничений. Он также обеспечивает строгую проверку типов, и компилятор может проверить правильность. С этими новыми API ваш пример кода будет просто:
let myView = UIView()
myView.backgroundColor = UIColor.redColor()
self.view.addSubview(myView)
let margins = self.view.layoutMarginsGuide
myView.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor).active = true
myView.topAnchor.constraintEqualToAnchor(margins.topAnchor).active = true
myView.bottomAnchor.constraintEqualToAnchor(margins.bottomAnchor).active = true
myView.widthAnchor.constraintEqualToConstant(300.0).active = true
Нет необходимости явно добавлять ограничения в правильное представление и т. Д. Подробнее об этом методе создания ограничений можно прочитать здесь:
и здесь:
Кажется, в вашем коде есть некоторая двусмысленность: вы создаете UIView как myView, но добавляете представление в self.view и даже ограничиваете также для просмотра самого себя. Поэтому исправьте свой код и замените представление на myView. Во-вторых, установите значение falseTranslayesAutoresizingMaskIntoConstraints. Затем добавьте все ограничения в self.view. Это должно решить вашу проблему.
myView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addConstraints([trailingConstraint, bottomConstraint, widthConstraint])
VFL также лучший и чистый подход. Это фактически дает визуализацию того, как устанавливаются ограничения.