3

使用该NSLayoutAttributeCenterX属性时,乘数 1 会产生与引用视图匹配的中心。增加值将其向左移动,向 0 减小则将其向右移动。

通过使用 2.5、1 和 0.625 的乘数,我已经能够通过反复试验(在超级视图中均匀分布 3 个视图)大致达到我想要的结果。虽然乱七八糟,但我发现 200 位于参考视图的左边缘(也增加了更多,不会移动视图),而 0.5 位于右边缘的中心(向 0 减小确实将视图进一步向左移动) .

用于可视化的快速白板

所以这是我的问题:

  1. 这是什么?
  2. 有没有一个公式可以用来准确地以这种方式放置视图,还是会永远反复试验?
  3. 他们为什么要这样做?
4

2 回答 2

10

当乘数不是 1.0 时,弄清楚中心约束的含义是很棘手的。我在 Xcode 6 中做了一些实验,这是我的结论。

所讨论的约束具有形式A.center.x = B.center.x * m + c,其中AB是所涉及的视图,m是约束的乘数,并且c是约束的常数。

让我们假设 Bcenter.x由其他一些约束固定。然后我相信自动布局的行为就好像它使用了这个算法:

  1. 找到 A 和 B 的最近共同祖先视图。将此共同祖先称为 G。

  2. 令 bxg = G 坐标系中的 Bxcenter。您可以在代码中将其计算为CGFloat bxg = [G convertPoint:B.center fromView:B.superview].x.

  3. 在 G 的坐标系中计算 axg = A 的所需 x 中心。 CGFloat axg = bxg * m + c.

  4. 将 axg 转换为 的坐标系A.superview,并将其存储为A.center.x

好的,考虑到所有这些,我们如何使用中心约束来实现您的“均匀间隔视图”的目标?我们没有。

这就是问题所在。假设所有三个子视图都具有相同的宽度 w。(如果它们有不同的宽度,问题就更难了。)假设容器视图的宽度为 W。有四个边距(一个在最左边的子视图的左边,一个在左子视图和中间的子视图之间,一个在中间子视图和右子视图,右子视图右侧一个。)

因此,边距的宽度应该是 (W - 3 w) / 4。然后我们想以某种方式将其插入另一个约束。您想使用中心约束,但为简单起见,让我们考虑最左侧视图 L 上的左边缘约束。我们希望约束为 L.left = (W - 3 w) / 4。这个约束对于自动布局直接处理。自动布局约束只能涉及两个视图属性,但这涉及三个。

解决方案是引入间隔视图。让我们从我们想要的三个子视图开始:

起始视图

我已经将这三个子视图中的每一个都限制为 80x80 并且垂直居中。

现在我将添加四个间隔视图,以灰色显示:

添加了间隔视图

我已经限制了每个垫片的高度和垂直中心,但我没有限制它们的宽度。我接下来要做的是将所有垫片限制为具有相等的宽度:

等宽

然后我将每个间隔的前缘和后缘固定到它最近的邻居,手动将常数设置为零。这是我做第一个垫片的方法:

间隔边缘

我对其他三个垫片做同样的事情。我不会在这里展示。

当我选择视图控制器并要求 Xcode 更新所有帧时,我得到均匀分布的视图:

更新帧

因为我实际上不希望在运行时显示间隔,所以我将选择它们并将它们设置为隐藏。 隐藏的视图仍然参与布局。

隐藏垫片

现在,如果子视图的宽度不一样怎么办?让我们改变蓝色子视图的宽度:

更改蓝色子视图的宽度

自动布局会更新框架,以使垫片继续具有相同的宽度。

于 2014-09-19T22:21:51.873 回答
0

我发现,如果您将视图与超级视图中心 X 对齐(我相信 Y 轴也是如此),那么您可以使用以下方法从预期的视图中心计算乘数系数:

Coeff = superview.width / view.center.X * 0.5

即你有宽度= 600的超级视图,你需要放置一个中心在0.25的超级视图宽度上的视图,然后视图中心= 150

Coeff = 600 / 150 * 0.5 = 2

如果您需要对称视图,那么

Coeff = 600 / 450 *0.5 = 0.666

因此,如果您知道视野中心 (CoV) 为 0.25,则公式为:

Coeff = 1 / CoV * 0.5
于 2015-01-23T13:23:46.393 回答