Masonry 仍然在维持. 如果使用 Swift 开发, 建议使用 SnapKit.

Masonry 以一种简便可读的代码实现子控件自动布局 ,甚至可以实现一些动画,是一中轻量级的框架。

Masonry 支持 iOS 和 Mac OS X。可以使用Pod安装或则下载ZIP直接导入使用。

如果不想使用前缀'mas_',可以导入宏,具体如下:

#define MAS_SHORTHAND
#define MAS_SHORTHAND_GLOBALS
#import "Masonry.h"

下载链接点击打开

官方说明

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.view;

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 as NSLayoutConstraint 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 call view1.translatesAutoresizingMaskIntoConstraints = NO; for you.

Not all things are created equal

.equalTo equivalent to NSLayoutRelationEqual

.lessThanOrEqualTo equivalent to NSLayoutRelationLessThanOrEqual

.greaterThanOrEqualTo equivalent to NSLayoutRelationGreaterThanOrEqual

These three equality constraints accept 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/NSView

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

Auto 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));

// 关键在此,不想使用前缀"mas_",在#import"Masonry" 上写入以下宏 //define this constant if you want to use Masonry without the 'mas_' prefix
#define MAS_SHORTHAND //define this constant if you want to enable auto-boxing for default syntax
#define MAS_SHORTHAND_GLOBALS // 就像下例所示 #define MAS_SHORTHAND
#define MAS_SHORTHAND_GLOBALS
#import "Masonry.h" ...
By default, macros which support [autoboxing](https://en.wikipedia.org/wiki/Autoboxing#Autoboxing) are prefixed with `mas_`. Unprefixed versions are available by defining `MAS_SHORTHAND_GLOBALS` before importing Masonry. #### 4. NSArray An array of a mixture of any of the previous types
```obj-c
make.height.equalTo(@[view1.mas_height, view2.mas_height]);
make.height.equalTo(@[view1, view2]);
make.left.equalTo(@[view1, @100, view3.right]);

Learn to prioritize

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

Composition, composition, composition

Masonry 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 life

Sometimes 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. References

You 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_updateConstraints

Alternatively if you are only updating the constant value of the constraint you can use the convience method mas_updateConstraints instead of mas_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_remakeConstraints

mas_updateConstraints is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's where mas_remakeConstraints comes in.

mas_remakeConstraints is similar to mas_updateConstraints, but instead of updating constant values, it will remove all of its constraints 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 the Masonry iOS Examples project.

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 the Masonry iOS Examples project in the Masonry workspace.

Where should I create my constraints?

@implementation DIYCustomView

- (id)init {
self = [super init];
if (!self) return nil; // --- Create your views here ---
self.button = [[UIButton alloc] init]; return self;
} // tell UIKit that you are using AutoLayout
+ (BOOL)requiresConstraintBasedLayout {
return YES;
} // this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints { // --- remake/update constraints here
[self.button remakeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(@(self.buttonSize.width));
make.height.equalTo(@(self.buttonSize.height));
}]; //according to apple super should be called at end of method
[super updateConstraints];
} - (void)didTapButton:(UIButton *)button {
// --- Do your changes ie change variables that affect your layout etc ---
self.buttonSize = CGSize(200, 200); // tell constraints they need updating
[self setNeedsUpdateConstraints];
} @end

Installation

Use the orsome 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"

Code Snippets

Copy the included code snippets to ~/Library/Developer/Xcode/UserData/CodeSnippets to 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>}];

Features

  • Not 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.

TODO

  • Eye candy
  • Mac example project
  • More tests and examples

Masonry(AutoLayout)的使用的更多相关文章

  1. iOS开发 masonry 设置tableHeadView

    最近做公司项目,使用到到tableHeadView,一直习惯用masonry来设置约束,但是设置tableHeadView没有那么的简单.先看下效果图: 视图层次结构是这样的: 基础的创建工程项目之类 ...

  2. 开源 iOS 项目分类索引大全 - 待整理

    开源 iOS 项目分类索引大全 GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助 系统基础库 Category/Util sstoolkit 一套Cate ...

  3. GitHub上值得关注的iOS开源项目

    1.AFNetworking地址:https://github.com/AFNetworking/AFNetworking用于网络请求 2.JSONKit地址:https://github.com/j ...

  4. 史上最全的常用iOS的第三方框架

    文章来源:http://blog.csdn.net/sky_2016/article/details/45502921 图像: 1.图片浏览控件MWPhotoBrowser       实现了一个照片 ...

  5. 常用iOS的第三方框架

    图像:1.图片浏览控件MWPhotoBrowser       实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网络下载图片并进行缓存.可对图片进行缩放等 ...

  6. 开源 iOS 项目分类索引大全

    GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助 系统基础库 Category/Util sstoolkit 一套Category类型的库,附带很多自定义 ...

  7. iOS 常用第三方

    MWPhotoBrowser 非常好用的图片浏览器 FDFullscreenPopGesture 用于全屏滑动切换视图 Aspects 用于快速AOP编程 AFNetworking iOS开发中最为火 ...

  8. iOS --- [持续更新中] iOS移动开发中的优质资源

    在我们做iOS APP的开发过程中, 须要非常多设计, 产品, 技术, 运营等方面的技巧和资源. 现将其整理汇总, 本文会一直持续更新. 敬请关注. 设计 Dribbble Dribbble是一个面向 ...

  9. iOS常用第三方类库及Xcode插件

    第三方类库(github地址): 1.AFNetworking 网络数据     https://github.com/AFNetworking/AFNetworking 2.SDWebImage 图 ...

随机推荐

  1. Swift注释

    Swift 中的普通注释与 Objective-C 中的一致,大概分为以下三种 // 单行注释 何问起 / *  多行注释 hovertree.com */ /// 标记注释1 http://hove ...

  2. python flask detect browser language

    python flask detect browser language   No problem. We won't show you that ad again. Why didn't you l ...

  3. JMS中的消息通信模型

    1. MQ简介: 消息队列(Message Queue,简称MQ),是应用程序与应用程序之间的一种通信方法.应用程序通过发送和检索出入列队的针对应用程序的数据 - 消息来通信,而无需专用连接来链接它们 ...

  4. mysql 增、删、改、查 、函数、执行次序

    这些是最基础的部分,若果这些不能满足你的需求,可以到http://www.w3school.com.cn中查询 增删改: 增 insert into<表名>(<列名列表>(如果 ...

  5. 我的css笔记

    1.css的使用方法 内嵌样式 <p style="font-size:20pt;color:red;">这个Style定义<p> <!--里面的文字 ...

  6. UVA 10089 Repackaging 数学问题

    大致题意:给出几个包裹,每个包裹都包装好了3种大小的杯子.现在要重新包装,使向量 a[1]*(s[1][1],s[1][2],s[1][3])+a[2]*(s[2][1],s[2][2],s[2][3 ...

  7. jQuery实现发送短信验证码后60秒倒计时

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script sr ...

  8. php取默认值以及类的继承

    (1)对于php的默认值的使用和C++有点类似,都是在函数的输入中填写默认值,以下是php方法中对于默认值的应用: <?phpfunction makecoffee($types = array ...

  9. shell脚本(管理守护进程)

    工作中常常会遇到处理消息队列的消费者进程,这样的进程是一个守护进程,即一个服务.服务通常写个shell脚本来管理,查询服务的status  ,启动start 关闭stop  重启reload.最近在学 ...

  10. PHP内核探索之变量(1)Zval

    作为数据的容器,我们常常需要跟变量打交道,不管这个变量是数字.数组.字符串.对象还是其他,因而可以说变量是构成语言的不可或缺的基础.本文是PHP内核探索之变量的第一篇,主要介绍zval的基本知识,包括 ...