Center views using *only* visual format?

148 Views Asked by At

I'm trying to center 2 views with different height vertically.

UILabel *view1 = [[UILabel alloc] init];
view1.backgroundColor = [UIColor redColor];
view1.text = @"view1\nline2";
view1.textAlignment = NSTextAlignmentCenter;
view1.numberOfLines = 0;
UILabel *view2 = [[UILabel alloc] init];
view2.backgroundColor = [UIColor greenColor];
view2.text = @"view2\nline2";
view2.textAlignment = NSTextAlignmentCenter;
view2.numberOfLines = 0;
[self.view addSubview:view1];
[self.view addSubview:view2];

NSDictionary *views = @{@"view1": view1, @"view2" : view2};

[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];

for (UIView *view in views.allValues) {
    [view setTranslatesAutoresizingMaskIntoConstraints:NO];
}

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view1]-[view2(==view1)]-|"
                                                                  options:NSLayoutFormatAlignAllCenterY
                                                                  metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=20)-[view1(200)]-(>=20)-|"
                                                                  options:NSLayoutFormatAlignAllCenterY
                                                                  metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=20)-[view2(100)]-(>=20)-|"
                                                                  options:NSLayoutFormatAlignAllCenterY
                                                                  metrics:nil views:views]];

This manages to make the centers of both aligned vertically, but they are at the bottom of the superview! enter image description here

I want to center vertically not only relative to each other, also in the superview.

I added a constraint like this and it works:

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

enter image description here

But I want to know, is this possible to achieve using only with visual format?

2

There are 2 best solutions below

1
On BEST ANSWER

Yes, it's possible, but only by adding spacer views. So if you create a couple of views, lets call them spacer1 and spacer2, you can center view1 with this string,

@"V:|[spacer1][view1][spacer2(==spacer1)]|"

This assumes that view1 has a fixed height. I wouldn't recommend doing it this way though, I would just use the code you show at the bottom of your post.

2
On

What about calculating the Y in "metrics" ?

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-centerY-[view1(200)]-(>=20)-|"
                                                                  options:NSLayoutFormatAlignAllCenterY
                                                                  metrics:@{@"centerY": @(CGRectGetHeight(self.view.frame)/2.0 - 100)}
                                                                    views:views]];