Masonry

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

非常好用,强烈推荐github地址例如:

[label mas_makeConstraints:^(MASConstraintMaker *make){

make.size.mas_equalTo(CGSizeMake(kScreen_Width, 100)); //设置label的大小

make.top.equalTo(_bottomView); //label的顶部和_bottomView相同

}];

ReadMe:MasonryMasonry is being dePRecated into a bugfix only state as more developers will be moving to Swift. Going forward we recommend usingSnapKitas it supports Swift and provides better type safety with a simpler API.

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

Masonry supports iOS and Mac OS X.

For examples take a look at theMasonry iOS Examplesproject in the Masonry workspace. You will need to runpod installafter downloading.

What's wrong with NSLayoutConstraints?Under the hood Auto Layout is a powerful and flexible way of organising and laying out your views. However creating constraints from code is verbose and not very descriptive.

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.

Another option is to use Visual Format Language (VFL), which is a bit less long winded.

However the ASCII type syntax has its own pitfalls and its also a bit harder to animate asNSLayoutConstraint constraintsWithVisualFormat:returns an array.

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 even shorter

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {

make.edges.equalTo(superview).with.insets(padding);

}];

Also note in the first example we had to add the constraints to the superview[superview addConstraints:....

Masonry however will automagically add constraints to the appropriate view.

Masonry will also callview1.translatesAutoresizingMaskIntoConstraints = NO;for you.

Not all things are created equal.equalToequivalent toNSLayoutRelationEqual

.lessThanOrEqualToequivalent toNSLayoutRelationLessThanOrEqual

.greaterThanOrEqualToequivalent toNSLayoutRelationGreaterThanOrEqual

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

1. MASViewAttributemake.centerX.lessThanOrEqualTo(view2.mas_left);

MASViewAttributeNSLayoutAttributeview.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/NSViewif 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. NSNumberAuto Layout allows width and height to be set to constant values.

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

//width >= 200 && width <= 400

make.width.greaterThanOrEqualTo(@200);

make.width.lessThanOrEqualTo(@400)

However Auto Layout does not allow alignment attributes such as left, right, centerY etc to be set to constant values.

So if you pass a NSNumber for these attributes Masonry will turn these into constraints relative to the view’s superview ie:

//creates view.left = view.superview.left + 10

make.left.lessThanOrEqualTo(@10)

Instead of using NSNumber, you can use primitives and structs to build your constraints, like so:

make.top.mas_equalTo(42);

make.height.mas_equalTo(20);

make.size.mas_equalTo(CGSizeMake(50, 100));

make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0));

make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));

By default, macros which supportautoboxingare prefixed withmas_. Unprefixed versions are available by definingMAS_SHORTHAND_GLOBALSbefore importing Masonry.

4. NSArrayAn array of a mixture of any of the previous types

make.height.equalTo(@[view1.mas_height, view2.mas_height]);

make.height.equalTo(@[view1, view2]);

make.left.equalTo(@[view1, @100, view3.right]);

Learn to prioritize.priorityallows you to specify an exact priority

.priorityHighequivalent toUILayoutPriorityDefaultHigh

.priorityMediumis half way between high and low

.priorityLowequivalent toUILayoutPriorityDefaultLow

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.equalTo(label.mas_top).with.priority(600);

Composition, composition, compositionMasonry also gives you a few convenience methods which create multiple 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))

You can chain view attributes for increased readability:

// All edges but the top should equal those of the superview

make.left.right.and.bottom.equalTo(superview);

make.top.equalTo(otherView);

Hold on for dear lifeSometimes you need modify existing constraints in order to animate or remove/replace constraints.

In Masonry there are a few different approaches to updating constraints.

1. ReferencesYou can hold on to a reference of a particular constraint by assigning the result of a constraint make expression to a local variable or a class property.

You could also reference multiple constraints by storing them away in an array.

// in public/private interface

@property (nonatomic, strong) MASConstraint *topConstraint;

...

// when making constraints

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {

self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top);

make.left.equalTo(superview.mas_left).with.offset(padding.left);

}];

...

// then later you can call

[self.topConstraint uninstall];

2. mas_updateConstraintsAlternatively if you are only updating the constant value of the constraint you can use the convience methodmas_updateConstraintsinstead ofmas_makeConstraints

// this is Apple's recommended place for adding/updating constraints

// this method can get called multiple times in response to setNeedsUpdateConstraints

// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints

- (void)updateConstraints {

[self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {

make.center.equalTo(self);

make.width.equalTo(@(self.buttonSize.width)).priorityLow();

make.height.equalTo(@(self.buttonSize.height)).priorityLow();

make.width.lessThanOrEqualTo(self);

make.height.lessThanOrEqualTo(self);

}];

//according to apple super should be called at end of method

[super updateConstraints];

}

3. mas_remakeConstraintsmas_updateConstraintsis useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's wheremas_remakeConstraintscomes in.

mas_remakeConstraintsis similar tomas_updateConstraints, but instead of updating constant values, it will remove all of its contraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove.

- (void)changeButtonPosition {

[self.button mas_remakeConstraints:^(MASConstraintMaker *make) {

make.size.equalTo(self.buttonSize);

if (topLeft) {

make.top.and.left.offset(10);

} else {

make.bottom.and.right.offset(-10);

}

}];

}

You can find more detailed examples of all three approaches in theMasonry iOS Examplesproject.

When the ^&*!@ hits the fan!Laying out your views doesn't always goto plan. So when things literally go pear shaped, you don't want to be looking at console output like this:

Unable to simultaneously satisfy constraints.....blah blah blah....

(

"<NSLayoutConstraint:0x7189ac0 V:[UILabel:0x7186980(>=5000)]>",

"<NSAutoresizingMaskLayoutConstraint:0x839ea20 h=--& v=--& V:[MASExampleDebuggingView:0x7186560(416)]>",

"<NSLayoutConstraint:0x7189c70 UILabel:0x7186980.bottom == MASExampleDebuggingView:0x7186560.bottom - 10>",

"<NSLayoutConstraint:0x7189560 V:|-(1)-[UILabel:0x7186980] (Names: '|':MASExampleDebuggingView:0x7186560 )>"

)

Will attempt to recover by breaking constraint

<NSLayoutConstraint:0x7189ac0 V:[UILabel:0x7186980(>=5000)]>

Masonry adds a category to NSLayoutConstraint which overrides the default implementation of- (NSString *)description.

Now you can give meaningful names to views and constraints, and also easily pick out the constraints created by Masonry.

which means your console output can now look like this:

Unable to simultaneously satisfy constraints......blah blah blah....

(

"<NSAutoresizingMaskLayoutConstraint:0x8887740 MASExampleDebuggingView:superview.height == 416>",

"<MASLayoutConstraint:ConstantConstraint UILabel:messageLabel.height >= 5000>",

"<MASLayoutConstraint:BottomConstraint UILabel:messageLabel.bottom == MASExampleDebuggingView:superview.bottom - 10>",

"<MASLayoutConstraint:ConflictingConstraint[0] UILabel:messageLabel.top == MASExampleDebuggingView:superview.top + 1>"

)

Will attempt to recover by breaking constraint

<MASLayoutConstraint:ConstantConstraint UILabel:messageLabel.height >= 5000>

For an example of how to set this up take a look at theMasonry iOS Examplesproject in the Masonry workspace.

InstallationUse theorsomeCocoaPods.

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"

Code SnippetsCopy the included code snippets to~/Library/Developer/Xcode/UserData/CodeSnippetsto write your masonry blocks at lightning speed!

mas_make->[<view> mas_makeConstraints:^(MASConstraintMaker *make){<code>}];

mas_update->[<view> mas_updateConstraints:^(MASConstraintMaker *make){<code>}];

mas_remake->[<view> mas_remakeConstraints:^(MASConstraintMaker *make){<code>}];

FeaturesNot limited to subset of Auto Layout. Anything NSLayoutConstraint can do, Masonry can do too!

Great debug support, give your views and constraints meaningful names.

Constraints read like sentences.

No crazy macro magic. Masonry won't pollute the global namespace with macros.

Not string or dictionary based and hence you get compile time checking.TODOEye candy

Mac example project

More tests and examples

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航