0

How do I create a 2 x 2 grid of UIViews programmatically using constraints in objective-c?

For example, I have four UIViews with their names corresponding to their row/column position (oneOne, oneTwo, twoOne, twoTwo) as per the below image.

layout using constraints

Here is the code I am currently using:

-(void)buildGrid {

    [self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
   
    UIView *oneOne = [UIView new];
    [oneOne setBackgroundColor:[UIColor redColor]];
    [oneOne setTranslatesAutoresizingMaskIntoConstraints:NO];

    UIView *oneTwo = [UIView new];
    [oneTwo setBackgroundColor:[UIColor greenColor]];
    [oneTwo setTranslatesAutoresizingMaskIntoConstraints:NO];

    UIView *twoOne = [UIView new];
    [twoOne setBackgroundColor:[UIColor blueColor]];
    [twoOne setTranslatesAutoresizingMaskIntoConstraints:NO];

    UIView *twoTwo = [UIView new];
    [twoTwo setBackgroundColor:[UIColor purpleColor]];
    [twoTwo setTranslatesAutoresizingMaskIntoConstraints:NO];

    [self.view addSubview:oneOne];
    [self.view addSubview:oneTwo];
    [self.view addSubview:twoOne];
    [self.view addSubview:twoTwo];

    NSDictionary *viewsDict = NSDictionaryOfVariableBindings(oneOne, oneTwo, twoOne, twoTwo);



    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[oneOne]-10-[twoOne]-10-|"
                                                                  options:NSLayoutFormatDirectionLeadingToTrailing
                                                                  metrics:nil
                                                                    views:viewsDict]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[oneOne]-10-[twoOne]-10-|"
                                                                  options:NSLayoutFormatDirectionLeadingToTrailing
                                                                  metrics:nil
                                                                    views:viewsDict]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[oneTwo]-10-[twoTwo]-10-|"
                                                                  options:NSLayoutFormatDirectionLeadingToTrailing
                                                                  metrics:nil
                                                                    views:viewsDict]];


    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[twoOne]-10-[twoTwo]-10-|"
                                                                  options:NSLayoutFormatDirectionLeadingToTrailing
                                                                  metrics:nil
                                                                    views:viewsDict]];

}

I have followed several tutorials but none (so far) have described how to create this kind of 'grid' layout, they have been far simpler like a single 'column' of UIViews but when I had further 'columns' I get errors about not being able to maintain the constraints:

Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.

This code works fine if I make it four UIViews going down or accross the screen but not if I make it 2 x 2. What am I doing wrong?

Update

As per accepted answer the constraints should have been:

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[oneOne]-10-[twoOne(==oneOne)]-10-|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:viewsDict]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[oneTwo]-10-[twoTwo(==oneTwo)]-10-|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:viewsDict]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[oneOne]-10-[oneTwo(==oneOne)]-10-|"
                                                                  options:NSLayoutFormatDirectionLeadingToTrailing
                                                                  metrics:nil
                                                                    views:viewsDict]];


    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[twoOne]-10-[twoTwo(==twoOne)]-10-|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:viewsDict]];
6
  • Do you need to use Visual Format? I'd suggest using some kind of layouting library like Masonry or KeepLayout - it will be easier to create complex layouts from code with them. Commented Nov 10, 2015 at 9:21
  • In all constraints set options to 0 instead of NSLayoutFormatDirectionLeadingToTrailing and see if you get the desired result Commented Nov 10, 2015 at 9:24
  • I have never heard of these libraries, I'll take a look now. I was kind of hoping this layout would be fairly simple and not uncommon. Commented Nov 10, 2015 at 9:25
  • @harshayarabarla - Just tired options:0 and no difference, unfortunately. Commented Nov 10, 2015 at 9:26
  • 1) V:|-10-[oneOne]-10-[twoOne]-10-| 2) H:|-10-[oneOne]-10-[oneTwo]-10-| 3) V:|-10-[oneTwo]-10-[twoTwo]-10-| 4) H:|-10-[twoOne]-10-[twoTwo]-10-| keep these 4 constraints as it is and give options 0 for all of them..... i see in your second constraint you set horizontal constraint with vertical views Commented Nov 10, 2015 at 9:29

1 Answer 1

1

First of you have error in second constraint. It should be:

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[oneOne]-10-[oneTwo]-10-|"
                                                                  options:NSLayoutFormatDirectionLeadingToTrailing
                                                                  metrics:nil
                                                                    views:viewsDict]];

Also your layout still doesn't contain any information about subviews size (width and height). You have to add constraints like this (in pseudocode)

 oneOne.width = oneTwo.width = twoOne.width = twoTwo.width
 oneOne.height = oneTwo.height = twoOne.height = twoTwo.height
Sign up to request clarification or add additional context in comments.

2 Comments

This problem was caused by a combination of not setting the widths to anything and the correction of the second constraint as you highlighted. I have set the widths in the constraints themselves: "V:|-10-[oneOne]-10-[twoOne(==oneOne)]-10-|". Thanks.
Didn't even know about [twoOne(==oneOne)] trick, so also thank you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.