Autolayout - 使用NSLayoutAttributeCenterX时,乘数使用的比例是多少?

时间:2014-09-19 21:22:48

标签: ios autolayout nsautolayout ios-autolayout

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

通过使用2.5,1和0.625的乘数,我已经能够通过试验和错误(在超视图上均匀分布3个视图)大致获得我想要的结果。在弄乱的时候,我发现200在被引用视图的左边缘居中(也增加了比不移动视图更多),而0.5在右边缘居中(朝向0减少会进一步移动视图)左)。

quick whiteboard for visualization

以下是我的问题:

  1. 这是什么?
  2. 是否有一个公式我可以用这种方式准确地放置视图,还是永远是试错?
  3. 他们为什么要这样做?

2 个答案:

答案 0 :(得分:10)

确定当乘数不是1.0时中心约束意味着什么是棘手的。我在Xcode 6中做了一些实验,这是我的结论。

相关约束的格式为A.center.x = B.center.x * m + c,其中AB是所涉及的观点,m是约束的乘数,{c 1}}是约束的常量。

假设B' center.x由其他一些约束修正。然后我相信autolayout就像使用这个算法一样:

  1. 找到A和B最近的共同祖先视图。称这个共同的祖先G。

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

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

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

  5. 好的,所以尽管如此,我们如何使用中心约束来实现“均匀间隔视图”的目标?我们没有。

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

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

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

    starting views

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

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

    added spacer views

    我限制了每个垫片的高度和垂直中心,但我约束它们的宽度。我接下来要做的是约束所有的间隔物具有相同的宽度:

    equal widths

    然后我将每个垫片的前沿和后沿固定到最近的邻居,手动将常数设置为零。这是我如何做第一个垫片:

    spacer edges

    我对其他三个垫片做同样的事情。我在这里没有表现出来。

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

    update frames

    由于我实际上并不希望在运行时看到垫片,我会选择它们并将它们设置为隐藏。 隐藏的视图仍然参与布局。

    hide spacers

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

    change width of blue subview

    自动布局更新帧,使间隔符的宽度保持相等。

答案 1 :(得分: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