Search code examples
iosobjective-ciphoneipadautolayout

Objective-C - why the button is not aligned bottom center?


enter image description here

I have the button which is not aligned bottom center? Set to full screen:

enter image description here

Set to bottom center with auto layout:

#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
  UIButton *but= [UIButton buttonWithType:UIButtonTypeRoundedRect];
  [but addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
  int startHeight = 167;
  int frameHeight = self.view.frame.size.height - startHeight;
  [but setFrame:CGRectMake(0, startHeight, 320, frameHeight)];
  [but setTitle:@"Login" forState:UIControlStateNormal];
  [but setExclusiveTouch:YES];
  [but setImage:[UIImage imageNamed:@"Image"] forState:UIControlStateNormal];
  [self.view addSubview:but];


  NSDictionary *viewsDict = @{@"but" : but};
  [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-167-[but]-0-|"
                                                                    options:0 metrics:nil views:viewsDict]];
  [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[but]-0-|"
                                                                    options:0 metrics:nil views:viewsDict]];
}


-(void) buttonClicked:(UIButton*)sender {
  NSLog(@"you clicked on button %@", sender.tag);
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}


@end

Solution

  • Rather than using

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[but]-0-|"
    options:0 metrics:nil views:viewsDict]];
    

    use

    self.view.addConstraint(NSLayoutConstraint(item: but, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 0))
    

    EDIT

    Realized OP's code is Objective - C

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:but attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
    

    EDIT

    This is the code I have in my ViewDidLoad

    - (void)viewDidLoad {
        [super viewDidLoad];
        UIButton *but = [[UIButton alloc] init];
        [but setTitle:@"ABCD" forState:UIControlStateNormal];
        [but setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        int startHeight = 167;
        int frameHeight = self.view.frame.size.height - startHeight;
        [but setFrame:CGRectMake(0, startHeight, 320, frameHeight)];
        
        [but setTranslatesAutoresizingMaskIntoConstraints:false];
        [self.view addSubview:but];
        NSDictionary *viewsDict = @{@"button" : but};
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[button]-0-|"
                                                                          options:0 metrics:nil views:viewsDict]];
        NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:but attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
        constraint.active = true;
        [self.view addConstraint:constraint];
        [self.view layoutIfNeeded];
        // Do any additional setup after loading the view, typically from a nib.
    }
    

    And this is the output :)

    enter image description here

    Works like a charm :) Please check what statement are u missing ??

    Mistakes in your code :

    1. You missed "[but setTranslatesAutoresizingMaskIntoConstraints:false];"

    When you are applying auto layout constraint you inform iOS not convert the default autoresizing masks to auto layout constraints as it might conflict with your applied auto layout constraints :)

    2.constraint.active = true;

    After creating constraint make sure to activate it as perfectly pointed out by EmilioPelaez in comments:)