了解自动布局中的乘数以使用相对定位

时间:2014-11-17 01:24:39

标签: ios autolayout nslayoutconstraint

我试图了解如何利用自动布局相对于其他视图按百分比定位项目。

例如,我最近了解到,您可以使用以下内容指定视图底部应比其超级视图底部高出4%:

self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 0.96, constant: 0))

这对我来说很有意义,因为乘数为1会使其在视图的底部对齐,因此您可以通过将乘数更改为0.96来将该数量减少4%。

但你怎么能在另一个方向做同样的事情呢?你想指定一个标签的顶部应该从superview的顶部开始下降4%。如果您使用相同的行,但将属性更改为.Top,这意味着它将比superview的顶部高4%(但它实际上并没有将其移出屏幕)。你不能没有我想到的负数乘数,而且我不相信大于1的值会在常数为0时做任何事情。所以你如何得到这个设置?

我有同样的问题来实现前导和尾随。尾随很容易。如果你想要它从右边10%:

self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Trailing, relatedBy: .Equal, toItem: self.view, attribute: .Trailing, multiplier: 0.9, constant: 0))

这是有道理的,因为你将它拨回0.1或10%,而不是完全对齐1.0。但你如何做同样的领导?我以为你可以设置相对于视图尾随的标签前导,然后将乘数设置为0.1。在我看来,这意味着标签将从最右边开始,然后被拨回90%,因此从左边获得所需的10%。但情况并非如此,我不确定原因。

你能解释一下这是如何工作的,如何正确使用乘数来获得这些相对布局?

为了简单起见,让我们假设你想创建一个标签,其高度和最高分别是superview高度的10%,并且超过10%的superview&# 39; s宽度。在iPhone的纵向上,标签上方和下方的填充比在左侧和右侧的填充更多,就像这样(是的,它按比例绘制):
enter image description here

但是,让我们在iPad上说它会被视为一个完美的广场。因此,填充量将是相同的量,如下所示:
enter image description here

问题是如何将这些约束定义为动态值,而不是为常量设置固定值。我已经知道如何做到底部和尾随,但顶部和领先让我难过。我希望了解如何使用乘数来进行更高级的布局,例如,指定标签的顶部应该在另一个标签的底部下方10%,而不是将其设置为固定的恒定。

3 个答案:

答案 0 :(得分:27)

有几种方法可以做到这一点。在最简单的情况下,您几乎已经得到它:如果您希望水平边界为10%和90%,那么您需要指定两个关于后缘的约束超级视图 - 所以Subview.Trailing锁定Superview.Trailing的乘数为0.9,如你所说,但Subview.Leading也锁定Superview.Trailing,只是乘数0.1

enter image description here

(顶部/底部类似)

另一方面,你最后提到的情况稍微复杂一点:"指定标签的顶部应该在另一个标签的底部下方10%。"为此,您可能无法像以前的情况一样使用固定百分比插入。相反,您可以在它们之间创建一个不可见的间隔视图:使用Spacer.Height = 0.1 * Superview.Height添加约束,然后将其附加在两个标签之间。 (您也可以使用这些间隔视图处理前一种情况,但对于这种情况,它并非真的必要。)

答案 1 :(得分:8)

在我看来,“你不能有一个负面的乘数,我不认为,我不相信大于1的值在常数为0时做任何事情”暴露了你的理解偏差。

引擎盖下的规则只是一个线性方程式:

FirstItem.Attribute1 = (SecondItem.Attribute2 * Multiplier) + Constant

全部以分数衡量。如您所见,乘数(NSLayoutConstraint的属性)不是常数的乘数。按照等式,你不明白的将是明确的。

至于你的具体例子,@ Archaeopterasa提出了一个很好的解决方案,另一个如下所示:

基于你知道如何做底部和尾随的事实,我想你已经完成了这两个。然后添加另外两个约束,效果将是你想要的: set label's width to 80% superview's width set label's height to 80% superview's height

最后,如果你想在另一个标签的底部指定一个标签的顶部位置10%,似乎你不能在不编写代码行的情况下实现它。在运行时知道superview的高度后,必须使用代码来设置连接FirstItem和SecondItem的NSLayoutConstraint对象的常量。

首先,控制从一个标签拖动到另一个标签并选择“垂直间距”。(或者您可以通过其他方式执行此操作)

其次,需要一个引用插座:

@IBOutlet weak var tenPercentOfSuperview: NSLayoutConstraint!

然后,在适当的位置(例如,在viewDidLoad())

中执行此操作
let heightOfSuperview = self.view.bounds.height
tenPercentOfSuperview.constant = heightOfSuperview * 0.1

现在一切都好。

如果您想了解有关此主题的更多信息,建议使用Apple的文档:https://developer.apple.com/library/ios/recipes/xcode_help-IB_auto_layout/chapters/EditingConstraintAttributesintheAttributesInspector.html

答案 2 :(得分:4)

这是

令人难以置信的简单

这样做的方法。

只需添加'helper'或“measure”视图:

示例中的“计算助手”视图为黄色。

一般技术是如此简单明了 - 它不需要任何解释,你可以从图像中得到它。

这是iOS中“他们不会教你”的“房间里的大象”之一。但它在所有布局中都经常使用。

(事实上,Apple应该为这个目的制作一个特殊的UIView子类“度量” - 实际上,许多大型团队都是这样做的,具有明显的特征。)

enter image description here

注意图标#1位于“View 1/4”辅助视图的右端。

注意图标#3位于“View 3/4”辅助视图左端的中心位置。

你已经完成了,有一个霞多丽。

方便的是,在帮助器视图中,只需将乘数设置为您想要的任何值,具体取决于所需的感觉。在代码中更改这些代码,使用IBInspectable,动画等等,这非常容易......

enter image description here