自动布局让我的生活很困难。从理论上讲,当我转换的时候,它会非常有用,但我似乎一直在与它作斗争。

我做了一个演示项目来寻求帮助。有人知道如何使视图之间的空间增加或减少均匀,每当视图调整大小?

下面是三个标签(手动垂直对齐):

我想要的是,当我旋转时,它们均匀地调整间距(而不是视图大小)。默认情况下,顶部和底部视图向中心挤压:


当前回答

看,没有间隔!

根据我最初回答的评论部分的建议,特别是@Rivera的有用建议,我简化了我的原始答案。

我用动图来说明这有多简单。我希望这些动图对你有帮助。为了防止你对动图有问题,我在下面附上了旧的答案和简单的屏幕截图。

产品说明:

1)添加按钮或标签。我用了3个按钮。

2)从每个按钮添加一个中心x约束到superview:

3)从每个按钮添加一个约束到底部布局约束:

4)调整上文第3条添加的约束如下:

A)选择约束; B)去掉常数(设为0), c)更改乘数如下:取按钮数量+ 1,从顶部开始,设置乘数为buttonCountPlus1:1,然后是buttonCountPlus1:2,最后是buttonCountPlus1:3。(我在下面的旧答案中解释了我从哪里得到这个公式,如果你感兴趣的话)。

5)这里是一个演示运行!

注意:如果你的按钮有较大的高度,那么你需要在常量值中补偿这一点,因为约束是从按钮的底部开始的。


旧的答案


不管苹果的文档和Erica Sadun的优秀书籍(Auto Layout Demystified)说什么,没有间隔器也可以均匀地分隔视图。这在IB和代码中是非常简单的,适用于任意数量的元素。你所需要的是一个数学公式,叫做“剖面公式”。做起来比解释起来简单。我将尽我最大的努力在IB中演示它,但在代码中也很容易做到。

在这个例子中,你会

1)首先设置每个标签有一个中心约束。这很简单。只需从每个标签control拖动到底部。

2)按住shift,因为你也可以添加我们将要使用的另一个约束,即“底部空间到底部布局指南”。

3)选择“bottom space to bottom layout guide”,“在容器中水平居中”。对所有3个标签都这样做。

基本上,如果我们将我们想要确定其坐标的标签除以标签总数加1,那么我们就有一个数字可以加到IB中得到动态位置。我简化了这个公式,但你可以用它来设置水平间距或者同时设置垂直和水平间距。这是超级强大的!

这是乘数。

Label1 = 1/4 = .25,

Label2 = 2/4 = .5,

Label3 = 3/4 = .75

(编辑:@Rivera评论说,你可以简单地直接在乘数字段使用比率,xCode与做数学!)

4)所以,让我们选择Label1,并选择底部约束。是这样的:

5)在属性检查器中选择“第二项”。

6)在下拉菜单中选择“反转第一项和第二项”。

7)将常数归零,wC值为any。(如果需要,可以在这里添加偏移量)。

8)这是关键部分:在乘数字段中添加我们的第一个乘数0.25。

9)当你在它设置顶部的“第一项”为“CenterY”,因为我们想把它居中到标签的y中心。这是所有这些应该看起来的样子。

10)对每个标签重复这个过程,并插入相应的乘数:Label2为0.5,Label3为0.75。这里是最终产品在所有方向与所有紧凑的设备!超级简单。我一直在研究许多涉及大量代码和间隔的解决方案。这无疑是我在这个问题上看到的最好的解决办法。

更新:@kraftydevil补充说底部布局指南只出现在故事板中,而不是在xib中。在xibs中使用'Bottom Space to Container'。好赶上!

其他回答

我为第一个项目设置了宽度值(>=宽度)和每个项目之间的最小距离(>=距离)。然后我用Ctrl拖动第二个,第三个…项连接项之间的依赖项。

迟到的派对,但我有一个工作的解决方案,创建一个菜单水平间距。在NSLayoutConstraint中使用==可以很容易地做到这一点

const float MENU_HEIGHT = 40;

- (UIView*) createMenuWithLabels: (NSArray *) labels
    // labels is NSArray of NSString
    UIView * backgroundView = [[UIView alloc]init];
    backgroundView.translatesAutoresizingMaskIntoConstraints = false;

    NSMutableDictionary * views = [[NSMutableDictionary alloc] init];
    NSMutableString * format = [[NSMutableString alloc] initWithString: @"H:|"];
    NSString * firstLabelKey;

    for(NSString * str in labels)
    {
        UILabel * label = [[UILabel alloc] init];
        label.translatesAutoresizingMaskIntoConstraints = false;
        label.text = str;
        label.textAlignment = NSTextAlignmentCenter;
        label.textColor = [UIColor whiteColor];
        [backgroundView addSubview: label];
        [label fixHeightToTopBounds: MENU_HEIGHT-2];
        [backgroundView addConstraints: [label fixHeightToTopBounds: MENU_HEIGHT]];
        NSString * key = [self camelCaseFromString: str];
        [views setObject: label forKey: key];
        if(firstLabelKey == nil)
        {
            [format appendString: [NSString stringWithFormat: @"[%@]", key]];
            firstLabelKey = key;
        }
        else
        {
            [format appendString: [NSString stringWithFormat: @"[%@(==%@)]", key, firstLabelKey]];
        }
    }

    [format appendString: @"|"];

    NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat: (NSString *) format
                                                                               options: 0
                                                                               metrics: nil
                                                                                 views: (NSDictionary *) views];
    [backgroundView addConstraints: constraints];
    return backgroundView;
}

查看https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html,上面有关于解决问题的详细描述。

在InterfaceBuilder中解决这个问题非常简单:

设置居中标签(label2)为“水平容器中心”和“垂直容器中心”

选择居中标签和顶部标签(label1 + label2),并为垂直间距添加两个约束。大于或等于最小间距的一个。小于或等于最大间距的一个。

中间的标签和底部的标签(label2 + label3)也是如此。

此外,您还可以添加两个约束label1 -顶部空间到SuperView和两个约束label2 -底部空间到SuperView。

结果是所有4个空格的大小变化相同。

我一直在坐过山车,爱自动布局和讨厌它。喜欢它的关键似乎是接受以下几点:

接口构建器的编辑和“有帮助的”自动创建约束在大多数情况下几乎无用 创建类别来简化常见操作是一种拯救,因为代码是如此重复和冗长。

也就是说,你正在尝试的不是直接的,在接口构建器中很难实现。这在代码中很简单。这段代码,在viewDidLoad,创建和定位三个标签,你需要他们:

// Create three labels, turning off the default constraints applied to views created in code
UILabel *label1 = [UILabel new];
label1.translatesAutoresizingMaskIntoConstraints = NO;
label1.text = @"Label 1";

UILabel *label2 = [UILabel new];
label2.translatesAutoresizingMaskIntoConstraints = NO;
label2.text = @"Label 2";

UILabel *label3 = [UILabel new];
label3.translatesAutoresizingMaskIntoConstraints = NO;
label3.text = @"Label 3";

// Add them all to the view
[self.view addSubview:label1];
[self.view addSubview:label2];
[self.view addSubview:label3];

// Center them all horizontally
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

// Center the middle one vertically
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];

// Position the top one half way up
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:label2 attribute:NSLayoutAttributeCenterY multiplier:0.5 constant:0]];

// Position the bottom one half way down
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:label2 attribute:NSLayoutAttributeCenterY multiplier:1.5 constant:0]];

我说过,这段代码通过UIView中的一些类别方法简化了很多,但为了清晰起见,这里我做了很多。

对于感兴趣的人来说,这个类别在这里,它有一个方法,可以沿着特定的轴均匀地间隔一个视图数组。