以编程方式创建绑定到视图控制器边距的约束

Posted

技术标签:

【中文标题】以编程方式创建绑定到视图控制器边距的约束【英文标题】:Programmatically creating constraints bound to view controller margins 【发布时间】:2016-04-08 18:45:24 【问题描述】:

我正在尝试创建一个视图,该视图将充当一种“面板”,连接到视图控制器的右侧。

即绑定到父视图控制器的尾部、顶部和底部边距,静态宽度为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])

【问题讨论】:

你为什么不使用视觉格式语言呢? "H:[panel(300)]|"V:|[toplayout][panel][botlayout]|" 应该足够了。 【参考方案1】:

实际上你的代码中的问题是你没有将myviewtranslatesAutoresizingMaskIntoConstraints设置为false,每当你想使用自动布局约束时,你必须将视图的translatesAutoresizingMaskIntoConstraints设置为false . 另一个问题是您没有在 self.view 上添加myview 我已经更新了您的代码,并且根据您的限制它可以正常工作。

将以下代码放入您的 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))

【讨论】:

如果您想以更简单的方式以编程方式添加约束,那么您可以使用github.com/keshavvishwkarma/KVConstraintExtensionsMaster。 这么老的线程,这为我节省了很多时间。谢谢!【参考方案2】:

在上面的示例代码中,您似乎在几个地方混淆了viewmyView。在任何情况下,widthConstraint 应添加到 myViewtopConstrainttrailingConstraintbottomConstraint 应添加到 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

无需显式地将约束添加到正确的视图等。您可以在此处阅读有关此创建约束的方法的更多信息:

https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutAnchor_ClassReference/

这里:

https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutDimension_ClassReference/

【讨论】:

【参考方案3】:

您的代码中似乎有些含糊不清,您正在创建一个 UIView 作为 myView 但将视图添加到 self.view 甚至约束也查看自身。所以更正您的代码并用 myView 替换视图。 其次将TranslayesAutoresizingMaskIntoConstraints 设置为false。 然后将所有约束添加到self.view。这应该可以解决您的问题。

 myView.setTranslatesAutoresizingMaskIntoConstraints(false)
 self.view.addConstraints([trailingConstraint, bottomConstraint, widthConstraint])

VFL 也是一种更好、更干净的方法。它实际上给出了如何设置约束的可视化。

【讨论】:

以上是关于以编程方式创建绑定到视图控制器边距的约束的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式创建带有约束的视图

限制为边距的堆栈视图不会留下任何余量

以编程方式添加的约束不起作用

如何将约束添加到相对于父视图边距的按钮,使其显示为距上边距 30 和距右边距 30

如何定位具有对所有设备看起来相同的边距的视图?

以编程方式创建布局,使用堆栈视图和约束不起作用