Search code examples
iosobjective-cxcodeuiviewvisual-format-language

Laying out fire UIViews in a row with Autolayout Visual Format Language


So, I want to use the Autolayout Visual Format Language to place 4 UIViews in horizontal rows (from top to bottom, like keyboard rows)... but for some reason, it doesn't seem to be working as expected, as my views seem to wind up in a stack on top of each other... Probably due to a mistake in the Visual Format...

So I have my 4 UIViews as such:

UIView *rowOne = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[rowOne setBackgroundColor:[UIColor blueColor]];
[rowOne setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:rowOne];

UIView *rowTwo = [[UIView alloc] initWithFrame:CGRectMake(0, 50, 50, 50)];
[rowTwo setBackgroundColor:[UIColor greenColor]];
[rowTwo setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:rowTwo];

UIView *rowThree = [[UIView alloc] initWithFrame:CGRectMake(0, 100, 50, 50)];
[rowThree setBackgroundColor:[UIColor redColor]];
[rowThree setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:rowThree];

UIView *rowFour = [[UIView alloc] initWithFrame:CGRectMake(0, 150, 50, 50)];
[rowFour setBackgroundColor:[UIColor yellowColor]];
[rowFour setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:rowFour];

I add them to a dictionary:

NSDictionary *views = NSDictionaryOfVariableBindings(rowOne, rowTwo, rowThree, rowFour);

I create the constraints:

NSString *rowsVerticalConstraintsString = @"V:|-[rowOne][rowTwo][rowThree][rowFour]-|";
NSString *rowOneHorizontalConstraintString = @"H:|-[rowOne]-|";
NSString *rowTwoHorizontalConstraintString = @"H:|-[rowTwo]-|";
NSString *rowThreeHorizontalConstraintString = @"H:|-[rowThree]-|";
NSString *rowFourHorizontalConstraintString = @"H:|-[rowFour]-|";

NSArray *rowsVerticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:rowsVerticalConstraintsString
                                                                           options:NSLayoutFormatAlignAllLeft
                                                                           metrics:nil
                                                                             views:views];

NSArray *rowOneHorizontalConstraint = [NSLayoutConstraint constraintsWithVisualFormat:rowTwoHorizontalConstraintString
                                                                              options:NSLayoutFormatAlignAllLeft
                                                                              metrics:nil
                                                                                views:views];

NSArray *rowTwoHorizontalConstraint = [NSLayoutConstraint constraintsWithVisualFormat:rowOneHorizontalConstraintString
                                                                              options:NSLayoutFormatAlignAllLeft
                                                                              metrics:nil
                                                                                views:views];

NSArray *rowThreeHorizontalConstraint = [NSLayoutConstraint constraintsWithVisualFormat:rowThreeHorizontalConstraintString
                                                                              options:NSLayoutFormatAlignAllLeft
                                                                              metrics:nil
                                                                                views:views];

NSArray *rowFourHorizontalConstraint = [NSLayoutConstraint constraintsWithVisualFormat:rowFourHorizontalConstraintString
                                                                              options:NSLayoutFormatAlignAllLeft
                                                                              metrics:nil
                                                                                views:views];

and add the constraints to the view:

[self.view addConstraints:rowsVerticalConstraints];
[self.view addConstraints:rowOneHorizontalConstraint];
[self.view addConstraints:rowTwoHorizontalConstraint];
[self.view addConstraints:rowThreeHorizontalConstraint];
[self.view addConstraints:rowFourHorizontalConstraint];

The behaviour that I would expect would be that the views are laid out side-by-side vertically and stretched horizontally, but they seem to overlay each other...

Any idea what I need to change?


Solution

  • Note:when using auto layout,initWithFrame have no compact

    Your layout constraints does not have height constraints.You may set 4 views have same height

    NSString *rowsVerticalConstraintsString = @"V:|-[rowOne(==rowTwo)][rowTwo][rowThree(==rowTwo)][rowFour(==rowTwo)]-|";
    

    Then screenshot

    Also,you can set width to be 150,height 50

     NSString *rowsVerticalConstraintsString = @"V:|-[rowOne(50)][rowTwo(50)][rowThree(50)][rowFour(50)]";
    NSString *rowOneHorizontalConstraintString = @"H:|-[rowOne(150)]";
    NSString *rowTwoHorizontalConstraintString = @"H:|-[rowTwo(150)]";
    NSString *rowThreeHorizontalConstraintString = @"H:|-[rowThree(150)]";
    NSString *rowFourHorizontalConstraintString = @"H:|-[rowFour(150)]";
    

    Then screenshot