README.md 6.86 KB

Masonry

Masonary is a light-weight layout framework which wraps AutoLayout with a nicer syntax. Masonary has its own layout DSL which provides a chainable way of describing your NSLayoutConstraints which results in layout code which is more concise and readable.

Whats wrong with NSLayoutConstraints?

Imagine a simple example in which you want to have a view fill its superview but inset by 10 pixels on every side

UIView *superview = self;

UIView *view1 = [[UIView alloc] init];
view1.translatesAutoresizingMaskIntoConstraints = NO;
view1.backgroundColor = [UIColor greenColor];
[superview addSubview:view1];

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[superview addConstraints:@[

    //view1 constraints
    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeTop
                                multiplier:1.0
                                  constant:padding.top],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeLeft
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeLeft
                                multiplier:1.0
                                  constant:padding.left],   

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeBottom
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1.0
                                  constant:-padding.bottom],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeRight
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeRight
                                multiplier:1
                                  constant:-padding.right],

 ]];

Even with such a simple example the code needed is quite verbose and quickly becomes unreadable when you have more than 2 or 3 views.

Prepare to meet your Maker!

heres the same constraints created using MASConstraintMaker

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
    make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);
    make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}];

or ever shorter

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(superview).with.insets(padding);
}];

Not all things are created equal

.equalTo equivalent to NSLayoutRelationEqual

.lessThanOrEqualTo equivalent to NSLayoutRelationLessThanOrEqual

.greaterThanOrEqualTo equivalent to NSLayoutRelationGreaterThanOrEqual

These three equality constraints except one argument which can be any of the following:

1. MASViewAttribute

make.centerX.lessThanOrEqualTo(view2.mas_left);
MASViewAttribute NSLayoutAttribute
view.mas_left NSLayoutAttributeLeft
view.mas_right NSLayoutAttributeRight
view.mas_top NSLayoutAttributeTop
view.mas_bottom NSLayoutAttributeBottom
view.mas_leading NSLayoutAttributeLeading
view.mas_trailing NSLayoutAttributeTrailing
view.mas_width NSLayoutAttributeWidth
view.mas_height NSLayoutAttributeHeight
view.mas_centerX NSLayoutAttributeCenterX
view.mas_centerY NSLayoutAttributeCenterY
view.mas_baseline NSLayoutAttributeBaseline

2. UIView

if you want view.left to be greater than or equal to label.left :

//these two constraints are exactly the same
make.left.greaterThanOrEqualTo(label);

make.left.greaterThanOrEqualTo(label.mas_left);

3. NSNumber

if you want to set view to have a minimum and maximum width you could pass a number to the equality blocks:

view.width
    .greaterThanOrEqual(@200)
    .lessThanOrEqual(@400)

Learn to prioritize

.prority you ca specify an exact priority

.priorityHigh equivalent to UILayoutPriorityDefaultHigh

.priorityMedium is half way between high and low

.priorityLow equivalent to UILayoutPriorityDefaultLow

Priorities are can be tacked on to the end of a constraint chain like so:

make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow();

make.top.equal(label.mas_top).with.priority(600);

Composition, composition, composition

Masonry also gives you a few convenience methods which create mutliple constraints at the same time. These are called MASCompositeConstraints

edges

// make top, left, bottom, right equal view2
make.edges.equalTo(view2);

// make top = superview.top + 5, left = superview.left + 10,
//      bottom = superview.bottom - 15, right = superview.right - 20
make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))

size

// make width and height greater than or equal to titleLabel
make.size.greaterThanOrEqualTo(titleLabel) 

// make width = superview.width + 100, height = superview.height - 50
make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))

center

// make centerX and centerY = button1
make.center.equalTo(button1) 

// make centerX = superview.centerX - 5, centerY = superview.centerY + 10
make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))

For more usage examples take a look at the MasonryExamples project in the Masonry workspace.

Installation

Use the awesome CocoaPods. In your Podfile

pod 'Masonry'

If you want to use masonry without all those pesky 'mas_' prefixes. Add #define MAS_SHORTHAND to your prefix.pch before importing Masonry

#define MAS_SHORTHAND 

Get busy Masoning

#import "Masonry.h"

Features

  • No macro magic. Masonry won't pollute the global namespace with macros.
  • Not string or dictionary based and hence you get compile time checking.

TODO

  • Eye candy
  • Better debugging help for complicated layouts
  • Header comments/Documentation
  • More tests and examples