Haagenti
Haagenti

Reputation: 8144

iOS VFL display two button next eachother

I'm trying to learn Visual format language and in this case I want two button next each other in the top of the view.

This is my code but nothing appears?

UIButton *button1 = [[UIButton alloc] init];
[button1 setBackgroundColor:[UIColor blueColor]];
UIButton *button2 = [[UIButton alloc] init];
[button2 setBackgroundColor:[UIColor redColor]];
NSDictionary *views = NSDictionaryOfVariableBindings(button1, button2);
NSLog(@"%@", [views allKeys]);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"[button1(==button2)]" options:0 metrics:Nil views:views];
[self.view addSubview:button1];
[self.view addSubview:button2];
[self.view addConstraints:constraints];

Thanks to the answer this is now my code:

UIButton *button1 = [UIButton buttonWithType:UIButtonTypeSystem];
button1.translatesAutoresizingMaskIntoConstraints = NO;
[button1 setTitle:@"Button" forState:UIControlStateNormal];
[button1 setBackgroundColor:[UIColor redColor]];
[self.view addSubview:button1];

UIButton *button2 = [UIButton buttonWithType:UIButtonTypeSystem];
button2.translatesAutoresizingMaskIntoConstraints = NO;
[button2 setTitle:@"Button" forState:UIControlStateNormal];
[button2 setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:button2];

NSDictionary *views = NSDictionaryOfVariableBindings(button1, button2);
NSString *const kHConstraint = @"|-[button1(==button2)]-[button2]-|";
NSString *const kVConstraint = @"V:|-[button1(==44)]";
NSString *const kVConstraint2 = @"V:|-[button2(==44)]";
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:kHConstraint options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:kVConstraint options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:kVConstraint2 options:0 metrics:nil views:views]];

I am wandering if I could combine the two Vertical constraints into one?


Yes this is possible by using the option NSLayoutFormatAlignAllTop:

NSDictionary *views = NSDictionaryOfVariableBindings(button1, button2);
NSString *const kHConstraint = @"H:|-[button1(==button2)]-[button2]-|";
NSString *const kVConstraint = @"V:|-[button1(==button2)]";
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:kHConstraint options:NSLayoutFormatAlignAllTop metrics:metrics views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:kVConstraint options:0 metrics:metrics views:views]];

Great article from:@jrturton and can be found here

Upvotes: 2

Views: 417

Answers (1)

jrturton
jrturton

Reputation: 119242

  1. You need to turn off autoresizing for the two buttons:

    button1.translatesAutoresizingMaskIntoConstraints = NO;
    button2.translatesAutoresizingMaskIntoConstraints = NO;
    
  2. You have to specify enough constraints for the system to determine height, width and position for each subview. The default frame otherwise is CGRectZero which will be invisible.

  3. Currently your VFL string sets button1 to be equal in width to button2, but if both buttons are equally sized at zero, this still satisfies the constraints.
  4. Your constraints have no positioning information.

As a minimum, I'd suggest the following VFL statements to give you the layout you need:

@"V:|-[button1(==44)]"

This gives your button1 a height of 44, and positions it a standard inset from the top of the superview.

@"V:|[button2(==44)]"

This does the same to button 2. You can also achieve this by alignment options in the horizontal layout, but that will confuse things for the purposes of this answer.

@"|-[button1(==button2)]-[button2]-|"

This makes the buttons equal width, and also insets them from the superview's edges.

I have written about VFL at some length here which will hopefully help with your understanding.

Upvotes: 3

Related Questions