×

iOS UIView + Autolayout Category


Simple UIView + Autolayout Category

See how magic happens in Autolayout code. This category will simplify the autolayout code. You don't have to remember all the constraints . So lets start creating an Autolayout Category

Goto , File> New> File> Objective-C File in iOS Tab > Next >Enter Autolayout in File and UIView in Category . File Type: Category



Now two files will be created UIView+Autolayout.h and UIView+Autolayout.m.Please correct the name as per your need in interface line.

Copy this code in UIView + Autolayout.h File

#import <UIKit/UIKit.h>

@interface UIView (Autolayout)

- (void)autolayout;
- (void)topAlign:(CGFloat)pixels;
- (void)bottomAlign:(CGFloat)pixels;
- (void)topAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView;
- (void)leftAlign:(CGFloat)pixels;
- (void)rightAlign:(CGFloat)pixels;
- (void)leftAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView;
- (void)width:(CGFloat)pixels;
- (void)height:(CGFloat)pixels;
- (void)centerXAlign;
- (void)centerYAlign;
- (void)heightGreaterThanEqual:(CGFloat)pixels;
- (void)rightAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView;
-(void)relativeRightAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView;

@end

Copy this code in UIView + Autolayout.m File

#import "UIView+Autolayout.h"

@implementation UIView (Autolayout)


-(void)autolayout
{
    [self setTranslatesAutoresizingMaskIntoConstraints:NO];
}

-(void)topAlign:(CGFloat)pixels
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeTop multiplier:1 constant:pixels];
    [self.superview addConstraint:contraint];
}

-(void)bottomAlign:(CGFloat)pixels
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeBottom multiplier:1 constant:-pixels];
    [self.superview addConstraint:contraint];
}

- (void)bottomAlignEqualToView:(UIView*)equalView
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:equalView attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
    [self.superview addConstraint:contraint];
}


- (void)bottomAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:relativeView attribute:NSLayoutAttributeTop multiplier:1 constant:pixels];
    [self.superview addConstraint:contraint];
}


- (void)topAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:relativeView attribute:NSLayoutAttributeBottom multiplier:1 constant:pixels];
    [self.superview addConstraint:contraint];
}


- (void)topAlign:(CGFloat)pixels  eqaulToView:(UIView*)relativeView
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:relativeView attribute:NSLayoutAttributeTop multiplier:1 constant:pixels];
    [self.superview addConstraint:contraint];
}


-(void)leftAlign:(CGFloat)pixels
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeLeading multiplier:1 constant:pixels];
    [self.superview addConstraint:contraint];
}


-(void)rightAlign:(CGFloat)pixels
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:-pixels];
    [self.superview addConstraint:contraint];
}


-(void)leftAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:relativeView attribute:NSLayoutAttributeRight multiplier:1.0 constant:pixels];
    [self.superview addConstraint:contraint];
}


-(void)width:(CGFloat)pixels
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:pixels];
    [self.superview addConstraint:contraint];
}


-(void)height:(CGFloat)pixels
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:pixels];
    [self.superview addConstraint:contraint];
}


-(void)centerXAlign
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
    [self.superview addConstraint:contraint];
}


-(void)centerYAlign
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0];
    [self.superview addConstraint:contraint];
}

- (void)heightGreaterThanEqual:(CGFloat)pixels
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:self.superview attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0];
    [self.superview addConstraint:contraint];
}

-(void)rightAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:relativeView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-pixels];
    [self.superview addConstraint:contraint];
}


-(void)relativeRightAlign:(CGFloat)pixels  relativeToView:(UIView*)relativeView
{
    NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:relativeView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-pixels];
    [self.superview addConstraint:contraint];
}

@end

How to use this category and use Autolayout in simplest way ?

Let's create a Login Form using Autolayout using the UIView + Autolayout Category.

Final Output :-


#import "ViewController.h"
#import "UIView+Autolayout.h"

#define PADDING   12
@interface ViewController()
{
}
@end

@implementation  ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
   
    self.view.backgroundColor = [UIColor colorWithRed:240.0/255.0 green:240.0/255.0 blue:245.0/255.0 alpha:1.0];
    
    UIView *boxView = [[UIView alloc]init];
    [self.view addSubview:boxView];
    [boxView autolayout];
    [boxView leftAlign:PADDING];
    [boxView rightAlign:PADDING];
    [boxView topAlign:PADDING*3];
    [boxView height:200];
    
    boxView.backgroundColor = [UIColor whiteColor];
    
    
    UILabel *labelEmail = [[UILabel alloc]init];
    [boxView addSubview:labelEmail];
    [labelEmail autolayout];
    [labelEmail leftAlign:PADDING];
    [labelEmail topAlign:PADDING];
    [labelEmail height:24];
    [labelEmail width:84];
    labelEmail.text = @"Email :";
    labelEmail.textColor = [UIColor blackColor];
    
    
    UITextField *emailTextField = [[UITextField alloc]init];
    [boxView addSubview:emailTextField];
    [emailTextField autolayout];
 [emailTextField leftAlign:PADDING relativeToView:labelEmail];
    [emailTextField topAlign:PADDING];
    [emailTextField height:32];
    [emailTextField rightAlign:PADDING];
    emailTextField.placeholder = @" Email";
    emailTextField.layer.borderWidth = 1.0;
    emailTextField.layer.cornerRadius = 2.0;
    emailTextField.layer.borderColor = [UIColor lightGrayColor].CGColor;
    
    
    
    UILabel *labelPassword = [[UILabel alloc]init];
    [boxView addSubview:labelPassword];
    [labelPassword autolayout];
    [labelPassword leftAlign:PADDING];
 [labelPassword topAlign:PADDING relativeToView:labelEmail];
    [labelPassword width:84];
    [labelPassword height:24];
    labelPassword.text = @"Password :";
    labelPassword.textColor = [UIColor blackColor];
    
    
    UITextField *passwordTextField = [[UITextField alloc]init];
    [boxView addSubview:passwordTextField];
    [passwordTextField autolayout];
   [passwordTextField leftAlign:PADDING relativeToView:labelPassword];
    [passwordTextField topAlign:PADDING relativeToView:labelEmail];
    [passwordTextField height:32];
    [passwordTextField rightAlign:PADDING];
    passwordTextField.placeholder = @" Password";
    passwordTextField.layer.borderWidth = 1.0;
    passwordTextField.layer.cornerRadius = 2.0;
    passwordTextField.layer.borderColor = [UIColor lightGrayColor].CGColor;
    

    
    UIButton *buttonLogin = [[UIButton alloc]init];
    [boxView addSubview:buttonLogin];
    [buttonLogin autolayout];
    [buttonLogin centerXAlign];
 [buttonLogin topAlign:PADDING*2 relativeToView:labelPassword];
    [buttonLogin height:32];
    [buttonLogin width:120];
    [buttonLogin setTitle:@"Login" forState:UIControlStateNormal];
    [buttonLogin setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    buttonLogin.backgroundColor = [UIColor orangeColor];
    [buttonLogin addTarget:self action:@selector(loginBtnClicked) forControlEvents:UIControlEventTouchUpInside];
    buttonLogin.layer.cornerRadius = 2.0;    
}

#pragma mark - Actions
-(void)loginBtnClicked
{
    NSLog(@"Login Button Clikced");
}

@end

A short Description :-

As you have seen in previous Autolayout tutorial , there was big lengthy statement to give spacing from left ,like this

 NSLayoutConstraint *leadingBoxViewContraint = [NSLayoutConstraint constraintWithItem:boxView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:12];
    
[self.view addConstraint:leadingBoxViewContraint];

But using UIView + Autolayout Category statement look like

[boxView leftAlign:PADDING];

1) leftAlign is used to give spacing from left of superView

2) topAlign is used to give spacing from top of superView

3) rightAlign is used to give spacing from right of superView

4) bottomAlign is used to give spacing from bottom of superView

5) centerXAlign is used to bring the UIElement to center in x-Axis of superView

6) centerYAlign is used to bring the UIElement to center in y-Axis of superView

7) height is used to give the height to UIElement of superView

8) width is used to give the width to UIElement of superView

I assume you understood boxView creation and then Email Label creation. We will discuss about passwordLabel and password TextField.

What is relativeView ?

RelativeView is used to create a view relative to another view. For example , we created emailTextField after Email Label

[emailTextField leftAlign:PADDING relativeToView:labelEmail];

We defined PADDING as MACRO at top of code which is of 12px
emailTextField leftAlign is at 12px padding and  relative To View labelEmail .
[labelPassword topAlign:PADDING relativeToView:labelEmail];

We defined PADDING as MACRO at top of code which is of 12px
labelPassword topAlign is at 12px padding and  relative To View labelEmail .Beacuse we want labelPassword below labelEmail .

Similarly , we created passwordTextField relativeWith LabelPassword from leftAlign and relativeWith labelEmail from topAlign in this way.

[passwordTextField leftAlign:PADDING relativeToView:labelPassword];
[passwordTextField topAlign:PADDING relativeToView:labelEmail];

Similarly, buttonLogin is relativeWith labelPassword from topAlign of labelPassword

[buttonLogin topAlign:PADDING*2 relativeToView:labelPassword];