6

想象一下以下场景。你有一个 UIImageView 和一个 UIButton。第一个是 300x360,第二个是 210x70。imageview包含一个目录图像,上面button写着“打开目录”。

我想根据这些要求在主视图中定位元素:

  • 两个元素应水平居中,即center.x坐标应全部相等(视图、图像和按钮);

  • 这两个元素应该以下列方式垂直居中:分隔符(灵活)-图像视图-分隔符(固定,比如说 30 分)-按钮-分隔符(灵活)。最顶部和最底部的分隔符应该具有相同的大小(这就是居中的意思)。

我无法使用 NSLayoutConstraint 使其工作。

到目前为止,我所做的一直是使用NSLayoutAttributeCenterX和将两个元素的 X 坐标居中NSLayoutRelationEqual到相同的view属性。

根据我的想法,最后一部分是修复它们的垂直对齐。我尝试使用@"V:|-[imageview(360)]-[button(70)]-|"但它不起作用(Unable to simultaneously satisfy constraints.)。

如果我使用@"V:|-[imageview(360)]-[button]-|",我会得到部分好的。也就是说,顶部是完美的,但按钮被拉伸以填充内部分隔符和视图底部之间的间隙。

如何使这些元素固定大小并让自动布局弄清楚如何将它们放置在视图中?

4

3 回答 3

11

我能够通过执行以下操作来做到这一点:

NSNumber *sepHeight = @60.0F;

// Center the two views horizontally
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView
                                                      attribute:NSLayoutAttributeCenterX
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self.view
                                                      attribute:NSLayoutAttributeCenterX
                                                     multiplier:1
                                                       constant:0]];

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

// Position the two views one below the other, using the separator height defined above
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[imageview]-sepHeight-[button]"
                                                                  options:0
                                                                  metrics:NSDictionaryOfVariableBindings(sepHeight)
                                                                    views:views]];

// Force the button distance from the bottom to be the half of the size of the content
CGFloat constant = (imageview.frame.size.height + button.frame.size.height + [sepHeight floatValue]) / 2.0;
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:button
                                                      attribute:NSLayoutAttributeBottom
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self.view
                                                      attribute:NSLayoutAttributeCenterY
                                                     multiplier:1
                                                       constant:constant]];

棘手的部分是常量值。该值是所有视图高度的一半,包括它们的分隔符。这意味着,如果图像视图的高度为 360,按钮的高度为 70,分隔符为 60,则该常数将为 (360 + 70 + 60)/2 = 245。

确实应该有更聪明的方法,但现在我认为这没问题。

于 2013-06-25T18:02:29.940 回答
5

有两种方法可以解决这个问题。

  1. 正如@uchuugaka 建议的那样,将您的图像视图和按钮放在容器视图中。如果子视图被固定到容器的边缘(您可以相应地调整大小 - 高度将是 360 + 30 + 70 == 460),那么您就不会遇到相同的居中问题。然后您可以在视图中使用简单的 align-center-Y 约束。

  2. 您可以使用间隔视图。通过添加两个隐藏视图,您可以指定约束以将它们定位在您的图像视图和按钮的上方/下方,具有相同的高度,例如它们充当弹簧。这是使用您的尺寸执行此操作的代码:


- (void) viewDidLoad
{
    [super viewDidLoad];

    UIView* imageview = [UIView new];
    imageview.backgroundColor = [UIColor blueColor];
    imageview.translatesAutoresizingMaskIntoConstraints = NO;

    UIView* button = [UIView new];
    button.backgroundColor = [UIColor greenColor];
    button.translatesAutoresizingMaskIntoConstraints = NO;


    UIView* spacer1 = [UIView new];
    spacer1.backgroundColor = [[UIColor redColor] colorWithAlphaComponent: 0.5];
    spacer1.translatesAutoresizingMaskIntoConstraints = NO;
    spacer1.hidden = YES; // comment out to show spacer!

    UIView* spacer2 = [UIView new];
    spacer2.backgroundColor = [[UIColor redColor] colorWithAlphaComponent: 0.5];
    spacer2.translatesAutoresizingMaskIntoConstraints = NO;
    spacer2.hidden = YES; // comment out to show spacer!

    [self.view addSubview: imageview];
    [self.view addSubview: button];
    [self.view addSubview: spacer1];
    [self.view addSubview: spacer2];

    NSDictionary* views = NSDictionaryOfVariableBindings( imageview, button, spacer1, spacer2 );

    NSArray* constraints;
    constraints = [NSLayoutConstraint constraintsWithVisualFormat: @"V:|[spacer1(==spacer2)][imageview(360)]-30-[button(70)][spacer2(==spacer1)]|"
                                                          options: 0
                                                          metrics: nil
                                                            views: views];
    [self.view addConstraints: constraints];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageview
                                                          attribute:NSLayoutAttributeWidth
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:nil
                                                          attribute:NSLayoutAttributeNotAnAttribute
                                                         multiplier:1
                                                           constant:300]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:button
                                                          attribute:NSLayoutAttributeWidth
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:nil
                                                          attribute:NSLayoutAttributeNotAnAttribute
                                                         multiplier:1
                                                           constant:210]];


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

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:button
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1
                                                           constant:0]];
}
于 2013-06-25T19:09:23.070 回答
0

您需要使您的垂直空间等于或大于图像视图顶部和按钮底部的空间。但是,这听起来也像是简单地拥有包含图像和按钮的附加视图会更容易。然后在超级视图中将该视图 V 和 H 居中。

自动布局有时仍然意味着容器视图。

于 2013-06-25T14:32:40.007 回答