自动布局-6个视图等分

7

我想在一个视图中放置6个对象(按钮),但是它们应该遵循一些限制:

enter image description here

  • 两个顶部按钮应该与父视图(A)有相同的垂直距离
  • 两个底部按钮应该有相同的垂直距离 (C)
  • 中间的两个按钮应该在父视图的中心线上
  • 所有按钮之间的垂直距离(E)应该相同
  • 最后但并非最不重要的是-按钮应该为正方形(因此宽度和高度应该相同)
  • A=C
  • B=D

是否可以仅使用IB实现这种效果,还是需要使用额外的代码来添加约束?


我认为在IB中这是可能的。尽管我所有的布局都是用代码完成的。Xcode对xib的处理不太好。 - dasdom
但是,你如何设置宽度=高度的约束,并将其设置为所有按钮相同的值? - kender
[myView addConstraint:[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f]]; [我视图 addConstraint: [NSLayoutConstraint constraintWithItem:我的按钮属性:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:我的按钮属性:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f]]; - dasdom
你为一个按钮设置了宽度和高度,然后如果你从一个按钮控制拖动到另一个按钮,就会出现“等宽”和“等高”的选项。 - dariaa
这里有一个问题,所有的按钮是否需要彼此具有相同的高度和宽度?如果是的话,那么你的条件并不总是能够满足:如果 A != C,则“中间的两个按钮应该在父视图的中心线上”就不可能成立。 - dariaa
好的,A和C相等,就像B和D一样 :) - kender
2个回答

23

这是一个合理的请求,但是约束使用视图的属性来定义,不能与其他约束相关联。话虽如此,有几种方法:

  1. 布局指南: 一种不需要预先确定任何间距的方法是使用 UILayoutGuide 对象或者在 iOS 9 之前使用隐藏的视图,即具有清晰背景或透明度为零的视图,在按钮之间。

    添加这些布局指南和定义“间隔”视图大小相同并且具有在间隔中,父视图和将放在空隙中的按钮之间的约束,最终展示水平和垂直间隔视图:

    spacer views

    对于那些被称为 vspacerX 的红色 UIView 对象的约束等效的 VFL 是:

    H:|[vspacer1][button1(100)][vspacer2(==vspacer1)][button2(==button1)][vspacer3(==vspacer1)]|
    H:|[vspacer1][button3(==button1)][vspacer2][button4(==button1)][vspacer3]|
    H:|[vspacer1][button5(==button1)][vspacer2][button6(==button1)][vspacer3]|
    

    而对于被称为 hspacerX 的蓝色 UIView 对象的约束,则如下所示:

    V:|[hspacer1][button1(100)][hspacer2(==hspacer1)][button3(==button1)][hspacer3(==hspacer1)][button5(==button1)][hspacer4(==hspacer1)]|
    
V: |[hspacer1][button2(==button1)][hspacer2][button4(==button1)][hspacer3][button6(==button1)][hspacer4]|

你不必使用VFL定义这些约束,因为任何定义这些约束的方式都可以,但这只是一种简洁的格式,用于描述我采用的约束集合。

无论如何,当使用这些布局指南(或不可见视图)渲染视图时,它会产生均匀间隔的按钮,如下所示:

spacers hidden

另一种方法是使用六个“容器”视图,看起来像这样:

containers

这六个UIView对象的等效VFL可能如下所示:

H:|[container1][container2(==container1)]|
H:|[container3(==container1)][container4(==container1)]|
H:|[container5(==container1)][container6(==container1)]|
V:|[container1][container3(==container1)][container5(==container1)]| V:|[container2(==container1)][container4(==container1)][container6(==container1)]|

然后您可以将按钮添加到其中,使每个小容器中心对齐,然后使容器变为透明:

just buttons

这也起作用,但略有不同的间距(其中边距是视图之间间距的一半,而另一种方法保持边距与它们之间的间距相同)。

  • 堆栈视图: 在 iOS 9 中,您可以使用专门设计用于平均分配视图的UIStackView。在这种情况下,将每个放置两个按钮水平排列到三个堆栈视图中,然后将这些堆栈视图放置在一个垂直堆栈视图中。这样就可以实现六个大小相同的容器视图。

    请参阅WWDC 2015视频Cocoa Touch 的新功能

    堆栈视图的问题在于,它们可用于确保排列的子视图之间的间距均匀,但不会确保第一个排列的视图之前和最后一个排列的视图之后的间距。因此,解决这个问题的方法是,在水平堆栈视图中包括两个更多的零宽度视图(或垂直堆栈视图的零高度)。然后,当您在堆栈视图上使用均匀间距时,它还会为您提供所有排列的子视图之前和之后似乎是间距的效果。

  • 使用NSLayoutAttributeCenterXNSLayoutAttributeCenterY属性的multiple: 另一种技术涉及为六个按钮定义attribute:NSLayoutAttributeCenterXattribute:NSLayoutAttributeCenterY属性,但不是使用constant值来使用multiplier字段。这种技术更简单,但并不总是呈现所需的效果,因此,除非您确定要追求这种技术,否则我不会描述它。我已经进入tl:dr领域了。

  • 集合视图: 另一种方法是使用UICollectionView,它可以优雅地处理这种情况,它很好地设计让您以网格方式布局单元格。

  • 硬编码数值:为了完整起见,我会指出你可以简单地指定 A、B、C 和 D 的特定值(以及宽度和高度约束)。你甚至不必担心设置 E 约束,只需将中间两个视图的垂直中心约束设置为其 superview,你就完成了 (因为假设 A=C 和 B=D,E 表示的间距应该是前面步骤的自然结果)。如果你想根据设备大小和/或方向调整这些值,那么可以实现 viewWillLayoutSubviews 来根据视图大小调整这些约束的常量。


  • 这个答案非常详尽和棒极了! - Chris Livdahl

    2
    更新:我有一个更好的解决方案,不需要使用间隔符。在这里查看。
    好的,这可以很快地在IB中实现。它非常简单。这是一个图示,将帮助说明。 enter image description here 假设v1-6是您的按钮,s1-5是您的间隔符。 1)在IB中控制拖动所有由红线显示的连接。
    2)shift点击v1-6和pin图标(看起来像|-I-|),设置宽度和高度为确定值。还要将高度和宽度设置为相等。
    3)shift选择s1-4(不是5)并设置高度相等。不要给它一个确定的高度,因为这应该由系统计算。您可能还需要将s1-4的宽度设置为相等,但不要给它们一个确定的宽度。
    4)从中心视图控制拖动到前沿和后沿,并设置中心约束。
    因此,你可能会认为,好的,现在应该可以工作了。但事实并非如此。这是我的应用程序在纵向运行时,颜色略有不同。看起来不错。(请注意,一旦设置完成,您将使间隔线变为不可见状态)。

    enter image description here

    但是当我旋转时,哎呀!

    enter image description here

    这里发生了什么?一旦我们理解了出现的问题,解决起来非常容易。我们想要的是IB不要缩小我们的视图。我们希望IB能够根据需要调整间隔和空白的大小,但是保持我们的视图不变。基本上,IB已经将间隔在竖屏模式下缩小到极限,试图让所有内容适应屏幕,结果缩小了我们的视图。但是我们希望IB缩小视图和间隔之间的垂直空白,而不是缩小我们的视图。解决方案非常简单。我们只需要调整垂直间隔的优先级,就可以解决问题了。因此,在IB中选择垂直间隔,并将其优先级调整为750。垂直间隔线将显示为虚线。完成。

    enter image description here

    enter image description here

    好的,这就是我们所预期的一切。

    enter image description here

    “随着间隔物的明确:”

    enter image description here

    enter image description here


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接