当乘数不是 1.0 时,弄清楚中心约束的含义是很棘手的。我在 Xcode 6 中做了一些实验,这是我的结论。
所讨论的约束具有形式A.center.x = B.center.x * m + c
,其中A
和B
是所涉及的视图,m
是约束的乘数,并且c
是约束的常数。
让我们假设 Bcenter.x
由其他一些约束固定。然后我相信自动布局的行为就好像它使用了这个算法:
找到 A 和 B 的最近共同祖先视图。将此共同祖先称为 G。
令 bxg = G 坐标系中的 Bxcenter。您可以在代码中将其计算为CGFloat bxg = [G convertPoint:B.center fromView:B.superview].x
.
在 G 的坐标系中计算 axg = A 的所需 x 中心。 CGFloat axg = bxg * m + c
.
将 axg 转换为 的坐标系A.superview
,并将其存储为A.center.x
。
好的,考虑到所有这些,我们如何使用中心约束来实现您的“均匀间隔视图”的目标?我们没有。
这就是问题所在。假设所有三个子视图都具有相同的宽度 w。(如果它们有不同的宽度,问题就更难了。)假设容器视图的宽度为 W。有四个边距(一个在最左边的子视图的左边,一个在左子视图和中间的子视图之间,一个在中间子视图和右子视图,右子视图右侧一个。)
因此,边距的宽度应该是 (W - 3 w) / 4。然后我们想以某种方式将其插入另一个约束。您想使用中心约束,但为简单起见,让我们考虑最左侧视图 L 上的左边缘约束。我们希望约束为 L.left = (W - 3 w) / 4。这个约束对于自动布局直接处理。自动布局约束只能涉及两个视图属性,但这涉及三个。
解决方案是引入间隔视图。让我们从我们想要的三个子视图开始:
我已经将这三个子视图中的每一个都限制为 80x80 并且垂直居中。
现在我将添加四个间隔视图,以灰色显示:
我已经限制了每个垫片的高度和垂直中心,但我没有限制它们的宽度。我接下来要做的是将所有垫片限制为具有相等的宽度:
然后我将每个间隔的前缘和后缘固定到它最近的邻居,手动将常数设置为零。这是我做第一个垫片的方法:
我对其他三个垫片做同样的事情。我不会在这里展示。
当我选择视图控制器并要求 Xcode 更新所有帧时,我得到均匀分布的视图:
因为我实际上不希望在运行时显示间隔,所以我将选择它们并将它们设置为隐藏。 隐藏的视图仍然参与布局。
现在,如果子视图的宽度不一样怎么办?让我们改变蓝色子视图的宽度:
自动布局会更新框架,以使垫片继续具有相同的宽度。