Matt Fellows
Matt Fellows

Reputation: 6532

How do I use iOS auto layout to center buttons in a menu?

I'm trying to programmatically add buttons to the horizontal center of a menu in iOS. SO that each button appears underneath the previous button.

My Menu is a UIView called viewToPlaceButtonsOn and I've got a variable to store the last button placed called previousButton.

Seems fairly simple right? Can anyone help me work out why I'm getting this so wrong?

- (void)makeButton:(NSString*) buttonTitle {
    UIButton* menuButton = [[UIButton alloc] init];
    [menuButton setTitle: buttonTitle forState:UIControlStateNormal];
    [menuButton setBackgroundColor:[UIColor redColor]];
    [viewToPlaceButtonsOn addSubview:menuButton];

    [viewToPlaceButtonsOn addConstraint:[NSLayoutConstraint constraintWithItem:menuButton
                                                                 attribute:NSLayoutAttributeCenterX
                                                                 relatedBy:NSLayoutRelationEqual
                                                                    toItem:previousButton
                                                                 attribute:NSLayoutAttributeCenterX
                                                                multiplier:1.0f
                                                                  constant:0.0f]];

    [viewToPlaceButtonsOn addConstraint:[NSLayoutConstraint constraintWithItem:menuButton
                                                                 attribute:NSLayoutAttributeTop
                                                                 relatedBy:NSLayoutRelationEqual
                                                                    toItem:previousButton
                                                                 attribute:NSLayoutAttributeTop
                                                                multiplier:1.0f
                                                                  constant:50.0f]];

    [viewToPlaceButtonsOn addConstraint:[NSLayoutConstraint constraintWithItem:menuButton
                                                       attribute:NSLayoutAttributeWidth
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:nil
                                                       attribute:NSLayoutAttributeNotAnAttribute
                                                      multiplier:1.0F
                                                        constant:200]];

    [viewToPlaceButtonsOn addConstraint:[NSLayoutConstraint constraintWithItem:menuButton
                                                       attribute:NSLayoutAttributeHeight
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:nil
                                                       attribute:NSLayoutAttributeNotAnAttribute
                                                      multiplier:1.0F
                                                        constant:40]];

    NSLog(@"Button's Frame: %f x %f (%f x %f)", [menuButton frame].origin.x, [menuButton frame].origin.y, [menuButton frame].size.width, [menuButton frame].size.height);

    previousButton = menuButton;
}

Upvotes: 0

Views: 394

Answers (2)

gagarwal
gagarwal

Reputation: 4244

Try this, please tweak values as needed:

UIButton * menuButton = [UIButton new];
[menuButton setTitle: buttonTitle forState: UIControlStateNormal];
[menuButton setBackgroundColor: [UIColor redColor]];
[viewToPlaceButtonsOn addSubview: menuButton];

NSDictionary * views = NSDictionaryOfVariableBindings(viewToPlaceButtonsOn, menuButton, _previousButton);

NSNumber * menuButtonWidth  = @(120.f);
NSNumber * menuButtonHeight = @(44.f);
NSNumber * verticalSpacing = @(10.f);

NSDictionary * metrics = NSDictionaryOfVariableBindings(menuButtonWidth, menuButtonHeight, verticalSpacing);

[viewToPlaceButtonsOn addConstraints: [NSLayoutConstraint constraintsWithVisualFormat: @"V:[viewToPlaceButtonsOn]-(<=1)-[menuButton]"
                                                                              options: NSLayoutFormatAlignAllCenterX
                                                                              metrics: metrics
                                                                                views: views]];

[viewToPlaceButtonsOn addConstraints: [NSLayoutConstraint constraintsWithVisualFormat: @"V:[_previousButton]-(verticalSpacing)-[menuButton(==menuButtonHeight)]|"
                                                                              options: 0
                                                                              metrics: metrics
                                                                                views: views]];

Upvotes: 0

Brandon
Brandon

Reputation: 2427

A couple things immediately pop out to me. You need to set

menuButton.translatesAutoresizingMaskIntoConstraints = NO; 

In order for your constraints to be correct otherwise autolayout will add its own.

Also your NSLog will not be accurate because layout hasn't been run at that point. Once layoutSubviews has been called then your views frame will be set by autolayout. To confirm this you can use the debugger to print your button at the end of your method call

po menuButton

Then let it continue and then pause your program, copy and paste the memory address for your button that you get from the previous po statment and you should see that the frame was set

po 0x039484

Upvotes: 1

Related Questions