为什么不是相对于UIViewController视图的框架的自动布局约束

时间:2015-09-21 02:32:48

标签: ios autolayout

我对整个汽车约束系统感到困惑。为什么约束设置为常量?如果有约束点使得您的视图可以适应不同的屏幕大小,为什么不根据它们与self.view的框架的相关性来设置。

也许一个更具体的例子可以说明我的观点:

假设我有两个观点 - view1view2以及view1在IB中高于view2。当我在IB中设置它们的垂直间距约束时,我会得到类似的东西:

  

(对于view2)顶部空间:view1;等于:39

令我困惑的是,为什么不是这样的:

  

顶部空间:view1;等于:0.2 * self.view.bounds.height

当添加更多约束时,常量不是表示视图位置的最佳方式,当它们将在不同大小的屏幕上呈现时。

2 个答案:

答案 0 :(得分:2)

  

为什么约束设置为常量?

它们不一定只是常数。 NSLayoutConstraint同时包含multiplierconstant。乘数根据另一个视图的某个属性缩放约束,并添加常量。来自the docs

item1.attribute1 = multiplier × item2.attribute2 + constant

这个等式可能是你需要记住的关于布局约束的最重要的事情。通过将constant设置为0,您可以看到您可以完全相对于第二项的属性设置约束,或者您可以通过将item2设置为multiplier来使约束成为绝对约束并完全忽略Top Space to: view1 ; Equals: 0.2 * self.view.bounds.height 0,或者你可以一起使用它们。

  

如果有约束点使得您的视图可以适应不同的屏幕大小,那么为什么不根据它们与self.view框架的相关性来设置。

要点不仅仅是为了适应不同的屏幕尺寸 - 您可以使用约束来制作适应各种事物的界面。因此,您可以选择相互约束的对象。

  

令我困惑的是,为什么不是这样的:NSLayoutConstraints

使用这样的乘数当然可以通过约束来实现。如果您查看multiplier参考页面,可以很容易地看到如何在代码中设置它。要使用可视化编辑器执行此操作,请创建约束,然后在文档大纲中选择它。使用“属性”检查器根据您的喜好调整constanttop值(在您的示例中分别为0.2和0)。

更新:具体看一下您的示例,我认为您不能设置依赖于超级视图height的{​​{1}}约束。我能想到的最好的理由,也就是我的主要推测是,简单地缩放UI以匹配屏幕大小是一种很难使用户界面适应不同屏幕的方法。例如,如果你使用屏幕尺寸来定位按钮,你最终会在大型设备上放置很棒的大按钮,而在小设备上放置小按钮,这没有多大意义:用户的手指没有改变大小,读取文本的大小也没有。我认为此处的目标是鼓励开发人员调整其UI,以便在较大的设备上显示更多内容,而不是显示更大的内容。

当然,有一些间距问题应该随设备的大小而变化。例如,20px的保证金可能适合您的iPad应用程序,但您宁愿在小型设备上降低10px的保证金。对于这种事情,使用大小类是有意义的,这使您可以在不同类别的设备上使用不同的布局。您的布局仍然应该根据需要使用约束来适应特定设备,但是大小类可以解决大型设备的UI与小型设备的UI显着不同的事实。

此外,即使您在视觉上创建约束,也知道可以在运行时轻松调整与约束关联的值。您可以将视图连接到视图控制器中的插座,就像将视图连接到插座一样。在运行时,您可以使用插座访问已连接的约束,并根据需要调整constantmultiplier值。

答案 1 :(得分:0)

如果使用故事板,两个视图之间的距离通常是不变的。如果 你想要相对于UIViewController视图框架的约束,你可以在代码中设置约束。就像这样:

override func viewDidLoad() {
    super.viewDidLoad()

    var view1 = UIView()
    var view2 = UIView()

    let sapce = self.view.frame.size.height * 0.1

    let verticalSpacingConstraint = NSLayoutConstraint(item: view2,
                                                  attribute: NSLayoutAttribute.Top,
                                                  relatedBy: NSLayoutRelation.Equal,
                                                     toItem: view1,
                                                  attribute: NSLayoutAttribute.Bottom,
                                                 multiplier: 1,
                                                   constant: sapce)

}