Autolayout Tricks - Part 3

Thank you for following this series of Autolayout tricks so far.

Similar to previous posts, these tricks are also based on the ideas mentioned in iOS - Autolayout Mystified) by Erica Sadun

Today I am going to talk about another autolayout trick. How to arrange view in stacks. In short, it will allow multiple views to be arranged horizontally (Alternatively vertically too) so that they have uniform width and spacing irrespective of the count.

However, total width should be greater than or equal to the total spacing introduced between the views

1. Arranging two equal width views side by side with spacing

Say you have two views v1 and v2 you want to arrange side by side with padding of 30 and spacing of 20 between them. This can be done as follows :

For sake of clarity, let's assume that self.view is a parent view to which we are adding these views as subviews.


UIView *v1 = [UIView new];
UIView *v2 = [UIView new];
NSDictionary *views = NSDictionaryOfVariableBindings (v1, v2, centerFiddling);
[v1 setBackgroundColor:[UIColor blackColor]];
[v2 setBackgroundColor:[UIColor redColor]];
[autolayoutContentView addSubview:v1];
[autolayoutContentView addSubview:v2];
[autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[centerFiddling]-10-[v1(30)]"
								   options:kNilOptions
								   metrics:nil
								     views:views]];
[autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[centerFiddling]-10-[v2(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views]];
[autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-30-[v1(v2)]-20-[v2]-30-|"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views]];

Output:

two_views_side_by_side

2. Arranging 3 variable width views horizontally side by side

Again, for this example, let's assume that our 3 views are named as v3, v4 and v5 respectively.


    UIView *v3 = [UIView new];
    UIView *v4 = [UIView new];
    UIView *v5 = [UIView new];
    NSDictionary *views1 = NSDictionaryOfVariableBindings (v3, v4, v5, v1);
    [v3 setBackgroundColor:[UIColor blackColor]];
    [v4 setBackgroundColor:[UIColor lightGrayColor]];
    [v5 setBackgroundColor:[UIColor yellowColor]];
    [autolayoutContentView addSubview:v3];
    [autolayoutContentView addSubview:v4];
    [autolayoutContentView addSubview:v5];
    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v1]-10-[v3(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views1]];
    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v1]-10-[v4(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views1]];
    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v1]-10-[v5(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views1]];
    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[v3(<=50)]-[v4]-[v5(v3)]-10-|" options:nslayoutformatalignalltop metrics:nil views:views1]]; < code>

Output:

three_views_side_by_side

3. Arranging n variable width views side by side with equal size and width.

For simplicity's sake, I will assume that n = 5, width = 30 and padding = 10

Again, similar to previous example, let's assume that views which we are going to consider are v6, v7, v8, v9 and v10.

Here's how you can arrange them side by side with equal spacing and equal width for all of them.


    UIView *v6 = [UIView new];
    UIView *v7 = [UIView new];
    UIView *v8 = [UIView new];
    UIView *v9 = [UIView new];
    UIView *v10 = [UIView new];

    NSDictionary *views2 = NSDictionaryOfVariableBindings (v5, v6, v7, v8, v9, v10);

    [v6 setBackgroundColor:[UIColor blackColor]];
    [v7 setBackgroundColor:[UIColor lightGrayColor]];
    [v8 setBackgroundColor:[UIColor redColor]];
    [v9 setBackgroundColor:[UIColor greenColor]];
    [v10 setBackgroundColor:[UIColor darkGrayColor]];
    
    [autolayoutContentView addSubview:v6];
    [autolayoutContentView addSubview:v7];
    [autolayoutContentView addSubview:v8];
    [autolayoutContentView addSubview:v9];
    [autolayoutContentView addSubview:v10];

    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v5]-10-[v6(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views2]];
    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v5]-10-[v7(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views2]];
    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v5]-10-[v8(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views2]];
    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v5]-10-[v9(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views2]];
    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v5]-10-[v10(30)]"
                                  options:kNilOptions
                                  metrics:nil
                                    views:views2]];

    [autolayoutContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
                           @"H:|-10-[v6]-10-[v7(v6)]-10-[v8(v7)]-10-[v9(v8)]-[v10(v9)]-10-|"
                                  options:NSLayoutFormatAlignAllTop
                                  metrics:nil
                                    views:views2]];
   

Output:

n_views_side_by_side

My very special thanks to Erica Sadun for demonstrating these cool tricks