使用 TopLayoutGuide 的制图约束
Cartography constraints with TopLayoutGuide
我有一个视图,我希望它看起来像这样:
|---------------|
| | <- navBar
|---------------|
| | <- topView
|---------------|
| |
| |
| |
|---------------|
我想要的一切就是坚持 topView.top 到 navBar.bottom。我决定使用制图并实现以下代码(尝试坚持使用 MVC ofc):
在我的 UIViewController
子类中:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
aView?.topLayoutGuide = self.topLayoutGuide // where aView is my subclass of UIView, inserted in loadView method
}
在我的 UIView
子类中:
var topLayoutGuide: UILayoutSupport?
override func updateConstraints() {
var constraint = NSLayoutConstraint?()
layout(topView) { (topView) in
constraint = topView.top == topView.superview!.top
}
topView.superview!.removeConstraint(constraint!)
layout(topView) { topView in
topView.top == topView.superview!.top + (self.topLayoutGuide?.length ?? 0)
topView.height == 67
topView.left == topView.superview!.left
topView.width == topView.superview!.width
}
super.updateConstraints()
}
问题是我收到以下日志,但我不知道如何解决:
Unable to simultaneously satisfy constraints.
[...]
(
"<NSLayoutConstraint:0x7fe6a64e4800 V:|-(64)-[UIView:0x7fe6a6505d80] (Names: '|':MyApp.MyView:0x7fe6a360d4c0 )>",
"<NSLayoutConstraint:0x7fe6a3538a80 V:|-(0)-[UIView:0x7fe6a6505d80] (Names: '|':MyApp.MyView:0x7fe6a360d4c0 )>"
)
看来我需要一些帮助。如何正确地做到这一点?我不想在 UIViewController
中实施约束,也不想使用 Storyboards
.
感谢您的帮助!
一个解决方案:创建对该特定 NSLayoutConstraint
的引用,并更新其 constant
:
var topLayoutConstraint: NSLayoutConstraint!
override func updateConstraints() {
layout(topView) { topView in
topLayoutConstraint = topView.top == topView.superview!.top
topView.height == 67
topView.left == topView.superview!.left
topView.width == topView.superview!.width
}
super.updateConstraints()
}
...然后,您可以像这样调整 NSLayoutConstraint 的常量:
topLayoutConstraint.constant = 50
剩下的唯一问题是 - 你什么时候更新 topLayoutConstraint
?一种解决方案是创建一个协议,MyViewInterface
:
protocol MyViewInterface: class {
var topLayoutGuideLength: CGFloat { get set }
}
然后,在我们的UIView
中,当那个topLayoutGuideLength
属性改变的时候,我们调整NSLayoutConstraint
的constant
:
public class MyView: UIView, MyViewInterface {
public var topLayoutGuideLength: CGFloat = 0 {
didSet {
topLayoutConstraint.constant = topLayoutGuideLength
}
}
}
最后,在我们的 UIViewController
(我们的 topLayoutGuide
居住的地方):
public class myViewController: UIViewController {
private var myView: MyView
// ...
public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myView.topLayoutGuideLength = topLayoutGuide.length
}
}
最后的结果?每当 UIViewController
触发 viewDidLayoutSubviews()
时,我们的 myView
的 topLayoutGuideLength
属性 就会更新,这会触发 topLayoutConstraint
的更改constant
.
又一次缺少制图文档...
我在制图学中发现 topLayoutGuideCartography
和 bottomLayoutGuideCartography
属性作为 UIViewController
扩展。使用它们可以在不覆盖 viewDidLayoutSubviews
的情况下为您提供所需的输出
您可以简单地使用此 属性 来锚定视图的顶部。
override func updateConstraints() {
layout(topView) { topView in
topView.top == topLayoutGuideCartography
topView.height == 67
topView.left == topView.superview!.left
topView.width == topView.superview!.width
}
super.updateConstraints()
}
我有一个视图,我希望它看起来像这样:
|---------------|
| | <- navBar
|---------------|
| | <- topView
|---------------|
| |
| |
| |
|---------------|
我想要的一切就是坚持 topView.top 到 navBar.bottom。我决定使用制图并实现以下代码(尝试坚持使用 MVC ofc):
在我的 UIViewController
子类中:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
aView?.topLayoutGuide = self.topLayoutGuide // where aView is my subclass of UIView, inserted in loadView method
}
在我的 UIView
子类中:
var topLayoutGuide: UILayoutSupport?
override func updateConstraints() {
var constraint = NSLayoutConstraint?()
layout(topView) { (topView) in
constraint = topView.top == topView.superview!.top
}
topView.superview!.removeConstraint(constraint!)
layout(topView) { topView in
topView.top == topView.superview!.top + (self.topLayoutGuide?.length ?? 0)
topView.height == 67
topView.left == topView.superview!.left
topView.width == topView.superview!.width
}
super.updateConstraints()
}
问题是我收到以下日志,但我不知道如何解决:
Unable to simultaneously satisfy constraints.
[...]
(
"<NSLayoutConstraint:0x7fe6a64e4800 V:|-(64)-[UIView:0x7fe6a6505d80] (Names: '|':MyApp.MyView:0x7fe6a360d4c0 )>",
"<NSLayoutConstraint:0x7fe6a3538a80 V:|-(0)-[UIView:0x7fe6a6505d80] (Names: '|':MyApp.MyView:0x7fe6a360d4c0 )>"
)
看来我需要一些帮助。如何正确地做到这一点?我不想在 UIViewController
中实施约束,也不想使用 Storyboards
.
感谢您的帮助!
一个解决方案:创建对该特定 NSLayoutConstraint
的引用,并更新其 constant
:
var topLayoutConstraint: NSLayoutConstraint!
override func updateConstraints() {
layout(topView) { topView in
topLayoutConstraint = topView.top == topView.superview!.top
topView.height == 67
topView.left == topView.superview!.left
topView.width == topView.superview!.width
}
super.updateConstraints()
}
...然后,您可以像这样调整 NSLayoutConstraint 的常量:
topLayoutConstraint.constant = 50
剩下的唯一问题是 - 你什么时候更新 topLayoutConstraint
?一种解决方案是创建一个协议,MyViewInterface
:
protocol MyViewInterface: class {
var topLayoutGuideLength: CGFloat { get set }
}
然后,在我们的UIView
中,当那个topLayoutGuideLength
属性改变的时候,我们调整NSLayoutConstraint
的constant
:
public class MyView: UIView, MyViewInterface {
public var topLayoutGuideLength: CGFloat = 0 {
didSet {
topLayoutConstraint.constant = topLayoutGuideLength
}
}
}
最后,在我们的 UIViewController
(我们的 topLayoutGuide
居住的地方):
public class myViewController: UIViewController {
private var myView: MyView
// ...
public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myView.topLayoutGuideLength = topLayoutGuide.length
}
}
最后的结果?每当 UIViewController
触发 viewDidLayoutSubviews()
时,我们的 myView
的 topLayoutGuideLength
属性 就会更新,这会触发 topLayoutConstraint
的更改constant
.
又一次缺少制图文档...
我在制图学中发现 topLayoutGuideCartography
和 bottomLayoutGuideCartography
属性作为 UIViewController
扩展。使用它们可以在不覆盖 viewDidLayoutSubviews
您可以简单地使用此 属性 来锚定视图的顶部。
override func updateConstraints() {
layout(topView) { topView in
topView.top == topLayoutGuideCartography
topView.height == 67
topView.left == topView.superview!.left
topView.width == topView.superview!.width
}
super.updateConstraints()
}