0

How to center 4 UIButtons vertically in view, maintaining same space and height of the buttons using Auto Layout Constraints?

Screen shot is at http://i.stack.imgur.com/SkPQz.png

com.iavian
  • 327
  • 1
  • 4
  • 12
  • 1
    There's only so much Autolayout can do. What you ask for is complex behaviour. You'd need to use your own spatial skills to break down the problem into many. I could tell you step by step how you'd go about doing this, but you won't be able to apply it to other situations. Maybe someone could help you out by teaching you how to do it. – duci9y Jul 05 '14 at 16:41
  • check http://stackoverflow.com/questions/13075415/evenly-space-multiple-views-within-a-container-view – spassas Jul 05 '14 at 16:43

1 Answers1

0

Here's how to do it programmatically with code:

The whole idea is to wrap your buttons inside a container view which you then center to the view controller's view. That means all your buttons will be centered visually too since they're the subviews (assuming you have equally spaced out your subviews and that they are the same size).

Result

center a group of buttons visually using container view

Source Code

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self initView];
    [self addAllContraints];
}

-(void)initView
{
    // your 4 boxes
    self.box1 = [[UILabel alloc] init];
    self.box1.backgroundColor = [UIColor blueColor];
    self.box1.text = @"Box 1";
    self.box1.textAlignment = NSTextAlignmentCenter;

    self.box2 = [[UILabel alloc] init];
    self.box2.backgroundColor = self.box1.backgroundColor;
    self.box2.text = @"Box 2";
    self.box2.textAlignment = self.box1.textAlignment;

    self.box3 = [[UILabel alloc] init];
    self.box3.backgroundColor = self.box1.backgroundColor;
    self.box3.text = @"Box 3";
    self.box3.textAlignment = self.box1.textAlignment;

    self.box4 = [[UILabel alloc] init];
    self.box4.backgroundColor = self.box1.backgroundColor;
    self.box4.text = @"Box 4";
    self.box4.textAlignment = self.box1.textAlignment;


    // box container view to hold the 4 boxes.
    self.boxContainer = [[UIView alloc] init];



    // add subviews to views

    [self.boxContainer addSubview:self.box1];
    [self.boxContainer addSubview:self.box2];
    [self.boxContainer addSubview:self.box3];
    [self.boxContainer addSubview:self.box4];

    [self.view addSubview:self.boxContainer];
}

-(void)addAllContraints
{
    self.box1.translatesAutoresizingMaskIntoConstraints = NO;
    self.box2.translatesAutoresizingMaskIntoConstraints = NO;
    self.box3.translatesAutoresizingMaskIntoConstraints = NO;
    self.box4.translatesAutoresizingMaskIntoConstraints = NO;
    self.boxContainer.translatesAutoresizingMaskIntoConstraints = NO;

    id views = @{
                 @"box1": self.box1,
                 @"box2": self.box2,
                 @"box3": self.box3,
                 @"box4": self.box4,
                 @"boxContainer": self.boxContainer
                 };

    // ------------------------------------------------------
    // tell the box container to be in the middle of the
    // view controller's view, horizontally and vertically
    // and because all 4 boxes are subviews of box container
    // they will be visually centered to the view controller
    // ------------------------------------------------------
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.boxContainer attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.boxContainer attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];


    // ------------------------------------------------------
    // set all 4 boxes to be equal width
    // ------------------------------------------------------
    //
    // note:
    //
    // box1 to box 4 all are subviews of boxContainer
    // so the '|' refers to the superview which is
    // boxContainer in this case, not self.view
    // ------------------------------------------------------
    [self.boxContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[box1(150)]|" options:0 metrics:nil views:views]];
    [self.boxContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[box2(==box1)]|" options:0 metrics:nil views:views]];
    [self.boxContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[box3(==box1)]|" options:0 metrics:nil views:views]];
    [self.boxContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[box4(==box1)]|" options:0 metrics:nil views:views]];

    // ------------------------------------------------------
    // equally space out all 4 boxes vertically
    // and that all 4 boxes should have equal height
    // ------------------------------------------------------
    [self.boxContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[box1(40)]-10-[box2(==box1)]-10-[box3(==box1)]-10-[box4(==box1)]-10-|" options:0 metrics:nil views:views]];
}
Zhang
  • 11,253
  • 6
  • 51
  • 80
  • I thought so, but I felt it's a workaround and not a solution. Thanks – com.iavian Jul 07 '14 at 23:07
  • Why's it a work around? The alternative of not using a container view is to use one of the boxes that close to center and tell the other boxes to be offset from this box. This container view method is more clean. – Zhang Jul 08 '14 at 01:49
  • No where in the document Apple suggests so – com.iavian Jul 08 '14 at 11:45
  • Whether it is suggested in Apple's documentation or not, it's what I observed through doing it both ways with and without the container view. – Zhang Jul 09 '14 at 01:46