【问题标题】:Using Auto Layout to change spaces equally on resizing使用自动布局在调整大小时平等地改变空间
【发布时间】:2013-01-07 12:09:01
【问题描述】:

如果我的应用中有一个视图,其中包含 3 个子视图(例如),它们之间的间距如下:

TOP - 40 分 - SUBVIEW 1 - 60 分 - SUBVIEW 2 - 80 分 - SUBVIEW 3 - 80 分 - 底部

我了解如何使用自动布局来确保我的每个子视图保持其高度和宽度,并且我可以在 3.5 或 4 英寸的 iPhone 屏幕上对齐所有内容。


但我不知道我需要做什么样的约束,以便如果它针对 3.5" 屏幕对齐,然后转到 4" 屏幕,每个间距都会按比例增加(例如 40 点会前往 47、60 至 71、80 至 95 - 或附近)。

这可能吗?还是我需要使元素之间的所有间距都相等? (如果是这样,我怎样才能让它同样调整大小?)


我是自动布局的新手,所以如果我遗漏了任何内容,或者没有明确我的意思,请告诉我,谢谢。

【问题讨论】:

    标签: ios xcode ios6 autolayout


    【解决方案1】:

    诀窍是在视图之间不仅添加一个约束,而且添加两个约束。一种为“大于或等于”,一种为“小于或等于”。 最小尺寸(大于或等于)应该是 3.5" 显示器上的间距。 最大尺寸(小于或等于)应该是 4" 显示器上的间距。

    示例:

    TOP - 40 分 - SUBVIEW 1 - 60 分 - SUBVIEW 2 - 80 分 - SUBVIEW 3 - 80 分 - 底部

    顶部 - SUBVIEW1: 在 Interface Builder 中选择两者。添加约束“垂直间距”两次。 将 1 设置为大于或等于 40。 将另一个设置为 Lesser Then 或 Equal 47。

    所有 Greater Then 值的总和 + 视图的所有高度应为 480 像素 (3.5") 所有 Lesser Then 值的总和 + 视图的所有高度应为 568 像素 (4")

    【讨论】:

    • 太棒了!在我的情况下,它是 SuperView >= 0 到 SubView 和 SubView
    【解决方案2】:

    我不知道有什么简单的方法可以做到这一点。我做了一个所有空格都相等的地方,但要做到这一点,我必须用不可见的标签填充空格(只是没有标题的标签)。所以,我的 4 个可见对象和 5 个“间隔标签”都在彼此的顶部。我使 4 个可见对象都具有明确的高度,而没有固定高度的垫片,但设置为完全相同:

    -(void)viewDidLoad {
        [super viewDidLoad];
    
        NSMutableDictionary *viewsDict = [NSMutableDictionary dictionary];
        for (int i=1; i<5; i++) { // Labels with titles
            UILabel *b = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 44)];
             b.text = @"This is my label";
            [b setTranslatesAutoresizingMaskIntoConstraints:NO];
            [viewsDict setObject:b forKey:[NSString stringWithFormat:@"b%d",i]];
        }
    
        for (int i=1; i<6; i++) { // Spacer labels
            UILabel *l = [[UILabel alloc ]init];
            [l setTranslatesAutoresizingMaskIntoConstraints:NO];
            [viewsDict setObject:l forKey:[NSString stringWithFormat:@"l%d",i]];
        }
    
        for (id obj in viewsDict.allKeys) 
            [self.view addSubview:viewsDict[obj]];
    
        NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[l1][b1][l2(==l1)][b2][l3(==l1)][b3][l4(==l1)][b4][l5(==l1)]|"
                                                                       options:NSLayoutFormatAlignAllLeading
                                                                       metrics:nil
                                                                         views:viewsDict];
    
    
        NSArray *constraints2 = [NSLayoutConstraint constraintsWithVisualFormat:@"|-[b1]"
                                                                       options:0
                                                                       metrics:nil
                                                                         views:viewsDict];
    
    
        [self.view addConstraints:constraints];
        [self.view addConstraints:constraints2];
    } 
    

    为了使空间不同,我认为你必须使用更长的形式来表达约束,而不是视觉格式。下面的代码似乎对我有用。我使用与上面相同的视图定义,除了我将标题标签的数量减少到 3 个,将分隔符的数量减少到 4 个以匹配您的问题。相对间距应如您的示例中所示,2:3:4:4。

    NSLayoutConstraint *con1 = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTop relatedBy:0 toItem:viewsDict[@"l1"] attribute:NSLayoutAttributeTop multiplier:1 constant:0];
        NSLayoutConstraint *con2 = [NSLayoutConstraint constraintWithItem:viewsDict[@"l1"] attribute:NSLayoutAttributeBottom relatedBy:0 toItem:viewsDict[@"b1"] attribute:NSLayoutAttributeTop multiplier:1 constant:0];
        NSLayoutConstraint *con3 = [NSLayoutConstraint constraintWithItem:viewsDict[@"b1"] attribute:NSLayoutAttributeBottom relatedBy:0 toItem:viewsDict[@"l2"] attribute:NSLayoutAttributeTop multiplier:1 constant:0];
        NSLayoutConstraint *con4 = [NSLayoutConstraint constraintWithItem:viewsDict[@"l2"] attribute:NSLayoutAttributeBottom relatedBy:0 toItem:viewsDict[@"b2"] attribute:NSLayoutAttributeTop multiplier:1 constant:0];
        NSLayoutConstraint *con5 = [NSLayoutConstraint constraintWithItem:viewsDict[@"b2"] attribute:NSLayoutAttributeBottom relatedBy:0 toItem:viewsDict[@"l3"] attribute:NSLayoutAttributeTop multiplier:1 constant:0];
        NSLayoutConstraint *con6 = [NSLayoutConstraint constraintWithItem:viewsDict[@"l3"] attribute:NSLayoutAttributeBottom relatedBy:0 toItem:viewsDict[@"b3"] attribute:NSLayoutAttributeTop multiplier:1 constant:0];
        NSLayoutConstraint *con7 = [NSLayoutConstraint constraintWithItem:viewsDict[@"b3"] attribute:NSLayoutAttributeBottom relatedBy:0 toItem:viewsDict[@"l4"] attribute:NSLayoutAttributeTop multiplier:1 constant:0];
        NSLayoutConstraint *con8 = [NSLayoutConstraint constraintWithItem:viewsDict[@"l4"] attribute:NSLayoutAttributeBottom relatedBy:0 toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
        NSLayoutConstraint *con9 = [NSLayoutConstraint constraintWithItem:viewsDict[@"l1"] attribute:NSLayoutAttributeHeight relatedBy:0 toItem:viewsDict[@"l2"] attribute:NSLayoutAttributeHeight multiplier:.66 constant:0];
        NSLayoutConstraint *con10 = [NSLayoutConstraint constraintWithItem:viewsDict[@"l1"] attribute:NSLayoutAttributeHeight relatedBy:0 toItem:viewsDict[@"l3"] attribute:NSLayoutAttributeHeight multiplier:.5 constant:0];
        NSLayoutConstraint *con11 = [NSLayoutConstraint constraintWithItem:viewsDict[@"l1"] attribute:NSLayoutAttributeHeight relatedBy:0 toItem:viewsDict[@"l4"] attribute:NSLayoutAttributeHeight multiplier:.5 constant:0];
        NSLayoutConstraint *con12 = [NSLayoutConstraint constraintWithItem:viewsDict[@"b1"] attribute:NSLayoutAttributeLeading relatedBy:0 toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:100];
        NSLayoutConstraint *con13 = [NSLayoutConstraint constraintWithItem:viewsDict[@"b2"] attribute:NSLayoutAttributeLeading relatedBy:0 toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:100];
        NSLayoutConstraint *con14 = [NSLayoutConstraint constraintWithItem:viewsDict[@"b3"] attribute:NSLayoutAttributeLeading relatedBy:0 toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:100];
    
        NSArray *constraints = @[con1,con2,con3,con4,con5,con6,con7,con8,con9,con10,con11,con12,con13,con14];
        [self.view addConstraints:constraints];
    

    【讨论】:

    • 太好了,谢谢你的想法。我会尝试一下,看看我是否可以一起破解一些接近我想要的东西:)
    • 经过相当多的学习如何使用自动布局后,我成功地使用了您的想法。谢谢!
    • 对尝试此操作的其他人的建议,请检查是否有任何自动添加的高度限制 - 因为这可能导致整体高度大于旋转时的屏幕尺寸。如果有,您可以简单地将它们的优先级降低到低于您要应用的高度限制。
    • 另一个忠告,我在 Storyboards 中实现了这个工作——即图形而不是代码。