Ios7 自动布局中的弹簧:在Xcode 5中均匀分布视图(带约束)

Ios7 自动布局中的弹簧:在Xcode 5中均匀分布视图(带约束),ios7,interface-builder,constraints,xcode5,autolayout,Ios7,Interface Builder,Constraints,Xcode5,Autolayout,我了解在Interface Builder中对齐、调整大小和分布视图的旧Struts和Springs方法。然而,我似乎不知道如何使用Xcode 5的自动布局来均匀分布视图。有一种方法可以使用Xcode 4实现,但该选项已经不存在了 我有7个垂直排列的按钮。在3.5英寸的布局上,它看起来很棒。当我在4英寸的布局中预览屏幕时,所有的按钮都被紧紧地挤在一起,最后一个按钮下面有很大的空间 我希望它们保持相同的高度,但我希望它们之间的空间能够弯曲,这样它们就可以在屏幕上分散开来 我已经能够得到按钮的高度

我了解在Interface Builder中对齐、调整大小和分布视图的旧Struts和Springs方法。然而,我似乎不知道如何使用Xcode 5的自动布局来均匀分布视图。有一种方法可以使用Xcode 4实现,但该选项已经不存在了

我有7个垂直排列的按钮。在3.5英寸的布局上,它看起来很棒。当我在4英寸的布局中预览屏幕时,所有的按钮都被紧紧地挤在一起,最后一个按钮下面有很大的空间

我希望它们保持相同的高度,但我希望它们之间的空间能够弯曲,这样它们就可以在屏幕上分散开来

我已经能够得到按钮的高度来伸缩和填充空间,但这不是我想要的行为。我想学习如何使用自动布局来取代我以前的Springs行为,但我似乎找不到通过Interface Builder实现这一点的方法

我同意顶部按钮与顶部边缘的距离是固定的,或者与顶部边缘的距离是成比例的,底部按钮和底部边缘也是如此。这些对我来说不太重要,我对它们都很在行


但我确实需要弄清楚如何在视图中的每个项目之间均匀分配额外的空间。

编辑注意,在iOS 9中,这种技术将变得不必要,因为UIStackView将自动执行分配。我将补充说明这是如何工作的

如何使用自动布局执行均匀分布 仅在Interface Builder中执行此操作的最简单方法(而不是在代码中构造约束)是使用“间隔”视图:

  • 绝对定位顶部和底部按钮

  • 在所有按钮之间放置间隔视图。使用约束将其水平放置(最简单的方法是将其水平居中)并设置其宽度

  • 在每个按钮及其上方和下方的间隔视图之间进行约束,常数为0

  • 现在选择所有间隔视图并将其高度设置为相等

  • 第一个屏幕截图显示了我在IB中的设置:

    我故意不更正“错位视图”,因为我希望您在设计约束时看到它的样子。以下是4英寸和3.5英寸屏幕上的结果:

    我将间隔视图保留为黑色,只是为了向您展示这项技术是如何工作的,但在现实生活中,您当然会使它们透明,因此不可见!因此,用户只看到您的按钮,均匀分布在屏幕的任意高度

    使用此技术的原因是,尽管相等的概念执行您要求的值的分布,但约束只能在视图的各个方面之间应用相等;因此,我们需要额外的视图(间隔视图),这样我们就可以使一些东西与其他东西相等(这里是间隔视图的高度)

    其他办法 显然,更灵活的方法是在代码中指定约束。这听起来可能令人望而生畏,但是有很多第三方代码可以帮助您,例如


    例如,如果我们有一个(可能是看不见的)超视图,其高度作为一个边界来指示四个按钮的最大垂直分布,我们可以用
    常数
    0
    将它们的顶部固定到该超视图的垂直中心,但
    乘数
    0.000001
    0.66666
    1.33333
    2.0
    (如果我们有四个按钮);现在,按钮将保持垂直分布,即使superview根据屏幕高度或其他因素改变大小。[在Xcode 5.1中,可以在Interface Builder中进行设置,但在早期版本的Xcode中不可能进行设置。]

    在iOS 9/Xcode 7中,这个问题在IB中可以轻松解决。只需选择按钮(或任何您想要垂直分布的按钮),然后选择编辑器>嵌入>堆栈视图。然后,只需配置堆栈视图:

    • 提供用于定位和调整堆栈视图本身大小的约束。例如,将堆栈视图的四条边固定到其superview的四条边上

    • 设置堆栈视图的属性。在这种情况下,我们需要垂直轴、填充对齐、等间距分布

    就这些!但是,您可能会好奇这是如何工作的,因为仍然可以在代码中手动执行相同的操作。堆栈视图不是通过插入间隔视图,而是通过插入间隔导轨来执行分布。导向(UILayoutGuide)是一个轻量级对象,其行为类似于布局约束中的视图,但不是视图,因此不必使其不可见,也不承担视图的任何开销

    为了举例说明,我将在代码中说明堆栈视图的作用。假设我们有四个垂直分布的视图。我们为它们分配除分布以外的所有约束:

    • 它们都有绝对高度限制

    • 其左侧固定在超级视图的左侧,右侧固定在超级视图的右侧

    • 顶部视图的顶部固定到超级视图的顶部,底部视图的底部固定到超级视图的底部

    现在,假设我们将这四个视图引用为
    视图
    ,一个数组。然后:

    let guides = [UILayoutGuide(), UILayoutGuide(), UILayoutGuide()]
    for guide in guides {
        self.view.addLayoutGuide(guide)
    }
    NSLayoutConstraint.activateConstraints([
        // guide heights are equal
        guides[1].heightAnchor.constraintEqualToAnchor(guides[0].heightAnchor),
        guides[2].heightAnchor.constraintEqualToAnchor(guides[0].heightAnchor),
        // guide widths are arbitrary, let's say 10
        guides[0].widthAnchor.constraintEqualToConstant(10),
        guides[1].widthAnchor.constraintEqualToConstant(10),
        guides[2].widthAnchor.constraintEqualToConstant(10),
        // guide left is arbitrary, let's say superview margin
        guides[0].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
        guides[1].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
        guides[2].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
        // bottom of each view is top of following guide
        views[0].bottomAnchor.constraintEqualToAnchor(guides[0].topAnchor),
        views[1].bottomAnchor.constraintEqualToAnchor(guides[1].topAnchor),
        views[2].bottomAnchor.constraintEqualToAnchor(guides[2].topAnchor),
        // top of each view is bottom of preceding guide
        views[1].topAnchor.constraintEqualToAnchor(guides[0].bottomAnchor),
        views[2].topAnchor.constraintEqualToAnchor(guides[1].bottomAnchor),
        views[3].topAnchor.constraintEqualToAnchor(guides[2].bottomAnchor)
    ])
    

    (显然,我可以使用循环使代码更简洁明了,但为了清晰起见,我特意展开了循环,以便您可以看到模式和技术。)

    实际上,如果您真的愿意,可以继续使用弹簧和支柱。您的故事板可以关闭自动布局。或者,如果您想同时使用自动布局和弹簧撑杆,请使用包含按钮的superview创建一个nib(.xib文件),将nib设置为不使用自动l