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.
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.
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);
}];
.equalToequivalent to NSLayoutRelationEqual
.lessThanOrEqualToequivalent to NSLayoutRelationLessThanOrEqual
.greaterThanOrEqualToequivalent to NSLayoutRelationGreaterThanOrEqual
These three equality constraints except one argument which can be any of the following:
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 |
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);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)
.prorityyou ca specify an exact priority
.priorityHighequivalent to UILayoutPriorityDefaultHigh
.priorityMediumis half way between high and low
.priorityLowequivalent 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);Masonry also gives you a few convenience methods which create mutliple constraints at the same time. These are called MASCompositeConstraints
// 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))// 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))// 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.
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"- No macro magic. Masonry won't pollute the global namespace with macros.
- Not string or dictionary based and hence you get compile time checking.
- Better readme
- Better debugging help for complicated layouts
- Header comments/Documentation
- More tests and examples