簡體   English   中英

使用NSLayoutConstraint垂直居中兩個視圖

[英]Center two views vertically using NSLayoutConstraint

想象一下這個場景。 你有一個UIImageView和一個UIButton。 第一個是300x360,第二個是210x70。 imageview包含目錄圖像, button “打開目錄”。

我想根據這些要求在主視圖中定位元素:

  • 兩個元素應該水平居中,即center.x坐標應該全部相等(視圖,圖像和按鈕);

  • 兩個元素應按以下方式垂直居中:分隔符(靈活) - imageview - 分隔符(固定,假設30分) - 按鈕 - 分隔符(靈活)。 最上面和最下面的分隔符應該具有相同的大小(這是居中的含義)。

我無法使用NSLayoutConstraint使其工作。

到目前為止,我所做的一直是使用NSLayoutAttributeCenterXNSLayoutRelationEqual將兩個元素的X坐標NSLayoutRelationEqual到同一個view屬性。

根據我的想法,最后一部分是修復它們的垂直對齊。 我嘗試使用@"V:|-[imageview(360)]-[button(70)]-|" 但它不起作用( Unable to simultaneously satisfy constraints. )。

如果我使用@"V:|-[imageview(360)]-[button]-|" 我覺得一切都很好。 也就是說,頂部是完美的但是按鈕被拉伸以填充內部分隔符和視圖底部之間的間隙。

如何使這些元素固定大小並讓自動布局只是弄清楚如何將它們放在視圖中?

通過這樣做,我能夠做到這一點:

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]];

棘手的部分是恆定值。 該值是所有視圖高度的一半,包括它們的分隔符。 這意味着,如果imageview的高度為360,按鈕的高度為70,分隔符為60,則該常量將為(360 + 70 + 60)/ 2 = 245。

確實應該有一種更聰明的方式,但是現在我覺得這沒關系。

有兩種方法可以解決這個問題。

  1. 正如@uchuugaka建議的那樣,將您的imageview和按鈕放在容器視圖中。 如果將子視圖固定到容器的邊緣(您將相應地調整大小 - 高度為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]];
}

您需要使垂直空間等於或大於圖像視圖頂部和按鈕底部。 但是,這聽起來似乎更容易在包含圖像和按鈕的其他視圖上。 然后在超視圖中將視圖V和H居中。

自動布局有時仍表示容器視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM