在如今的iOS开发中,Autolayout已经是不得不使用了,而且是我们主动的去拥抱Autolayout。使用Autolayout最普遍的方式就是在xib或者storyboard中可视化的添加各种约束,这也是Autolayout入门需要掌握的,关于这部分内容,可以参考《iOS开发——Autolayout的实践与技巧》这篇博客。对于比较简单的App开发,可能使用可视化Autolayout也就足够了。但是如果UI布局稍微复杂多变一点,那么就不得不使用代码了。对于iOS原生的代码自动布局,真的是过于繁琐。所以这里就要来介绍目前广泛使用的第三方库Masonry的使用,入门非常的方便简单。也是一位合格的iOS开发者需要掌握的。博客案例代码上传至 https://github.com/chenyufeng1991/MasonryLearnDemo 。

(1)使用Cocoapods导入Masonry,对于如何使用Cocoapods,请参考《iOS包管理工具Cocoapods的安装与使用》这篇博客。Podfile文件如下:

platform:ios,'8.0'
pod 'Masonry'

(2)先对Masonry中的内容做一个简单的介绍:

Masonry中有三种添加约束的方法:

- (NSArray *)mas_makeConstraint:(void(^)(MASConstraintMaker *))block;

- (NSArray *)mas_updateConstraint:(void(^)(MASConstraintMaker *))block;

- (NSArray *)mas_remakeConstraint:(void(^)(MASConstraintMaker *))block;

mas_makeConstraint:只负责新增约束,初次设置约束使用;

mas_updateConstraint:更新block中出现的约束,如果找不到该约束,会新增约束。

mas_remakeConstraint:清除之前的所有约束,仅保留最新的约束。

(3)equalTo和mas_equalTo的区别

其实mas_equalTo是一个宏,源码中是这样定义的:

 #define mas_equalTo(...)                 equalTo(MASBoxValue((__VA_ARGS__)))#define mas_greaterThanOrEqualTo(...)    greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__)))#define mas_lessThanOrEqualTo(...)       lessThanOrEqualTo(MASBoxValue((__VA_ARGS__)))#define mas_offset(...)                  valueOffset(MASBoxValue((__VA_ARGS__)))

同时,这里涉及到两个简便写法,Masonry提供了不加mas_前缀的方法,只需要定义两个宏:

MAS_SHORTHAND宏:定义了MAS_SHORTHAND宏之后,就可以使用UIView,NSArray中不带mas_前缀的makeConstraint,updateConstraint,remakeConstraint方法,以及UIView中不带mas_前缀的Attribute。

MAS_SHORTHAND_GLOBALS:直接对equalTo传入基础类型,Masonry自动转化为NSValue对象。

(4)比例系数与常数系数

multipliedBy(0.5)可以用来设置比例系数。

Masonry有四种设置Constant的方法:

- (MASConstraint * (^)(MASEdgeInsets insets))insets;
- (MASConstraint * (^)(CGSize offset))sizeOffset;
- (MASConstraint * (^)(CGPoint offset))centerOffset;
- (MASConstraint * (^)(CGFloat offset))offset;

insets方法可以同时设置top,left,bottom,right,接收MASEdgeInsets类型,也就是UiEdgeInsets类型,使用UIEdgeInetMake方法设置。

sizeOffset方法设置width,height,接收CGSize类型,使用CGSizeMake方法设置。

centerOffset方法设置centerX(X轴中心),centerY(Y轴中心)。

offset方法可以设置所有的偏移常量。

(5)对于一个约束,实际表示的是不等或者相等关系:

aView.Leading = 1.0 * bView.Trailing + 10;

其中:

aView :Item1;

Leading:Attribute1;

= : Relationship;

1.0  :Multiplier

bView:Item2;

Trailing :Attribute2;

10 :Constant;

(6)MASConstraintMaker提供了22种Attribute类型:

 //第一类@property (nonatomic, strong, readonly) MASConstraint *left;@property (nonatomic, strong, readonly) MASConstraint *top;@property (nonatomic, strong, readonly) MASConstraint *right;@property (nonatomic, strong, readonly) MASConstraint *bottom;@property (nonatomic, strong, readonly) MASConstraint *leading;@property (nonatomic, strong, readonly) MASConstraint *trailing;@property (nonatomic, strong, readonly) MASConstraint *width;@property (nonatomic, strong, readonly) MASConstraint *height;@property (nonatomic, strong, readonly) MASConstraint *centerX;@property (nonatomic, strong, readonly) MASConstraint *centerY;@property (nonatomic, strong, readonly) MASConstraint *baseline;//第二类@property (nonatomic, strong, readonly) MASConstraint *leftMargin;@property (nonatomic, strong, readonly) MASConstraint *rightMargin;@property (nonatomic, strong, readonly) MASConstraint *topMargin;@property (nonatomic, strong, readonly) MASConstraint *bottomMargin;@property (nonatomic, strong, readonly) MASConstraint *leadingMargin;@property (nonatomic, strong, readonly) MASConstraint *trailingMargin;@property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins;@property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins;//第三类@property (nonatomic, strong, readonly) MASConstraint *edges;@property (nonatomic, strong, readonly) MASConstraint *size;@property (nonatomic, strong, readonly) MASConstraint *center;

第一类是基本属性,向下支持到iOS6,用的比较多。

第二类是边缘相关属性,向下支持到iOS8,由于版本要求比较高,所以用的比较少。

第三类是复合属性,edges(top,left,right,bottom),size(width,height),center(centerX,centerY).

(7)扩展UIView中的Attribute:

 @property (nonatomic, strong, readonly) MASViewAttribute *mas_left;@property (nonatomic, strong, readonly) MASViewAttribute *mas_top;@property (nonatomic, strong, readonly) MASViewAttribute *mas_right;@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom;@property (nonatomic, strong, readonly) MASViewAttribute *mas_leading;@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing;@property (nonatomic, strong, readonly) MASViewAttribute *mas_width;@property (nonatomic, strong, readonly) MASViewAttribute *mas_height;@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX;@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY;@property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline;@property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr);@property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin;@property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin;@property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin;@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin;@property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin;@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin;@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins;@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins;

基本和MASConstraintMaker中的属性一样,只是每个属性前面都有mas_前缀,因为这个类是扩展UIView的,为了和系统类中的Attribute区别,所以加了前缀。

(8)SHORTHAND简便写法:Masonry提供了不加mas_前缀的方法,只需要定义几个宏:

---  MAS_SHORTHAND :定义了MAS_SHORTHAND宏之后,就可以使用UIView,NSArray中不带mas_前缀的makeConstraint,updateConstraint,remakeConstraint,以及UiView中不带mas_前缀的Attribute。

---  MAS_SHORTHAND_GLOBALS :直接对equalTo传入基础类型,Masonry自动转化为NSValue对象。

(9)with的使用

在Masonry的链式语法中,with可以对一个对象的多个属性进行连接,但也可以不用with.源码中的解释是:with是一个可选的语法属性,没有任何影响,但是能提高约束的可读性。

(10)小技巧

---  如果等式两边的Attribute是一样的,可以省略等式右边的Attribute;

---  如果是等于关系,并且右边的view是父view,equalTo也可以省略;

---  multipier默认为1时,可以不写;

---  offset默认为0时,可以不写;

---  所以,如果不嫌麻烦的话,可以对所有的约束添加multipliedBy()和offset(),看起来也会清楚直观。

(11)mas_key属性的使用:

mas_key相当于View原生的tag属性一样,是为了区分不同的View的,mas_key标志的是字符串,更加方便直观。如果在遇到约束冲突打印Log时,使用Key标识后,会很容易找到冲突位置。我下面会通过一个例子来讲解。

(12)weakSelf的使用

对于block中self的循环引用问题,可以参考《iOS开发——Block引起循环引用的解决方案》这篇博客。Masonry的约束也是写在block中,所以我通过一个宏定义:

//定义宏,用于block
#define WeakSelf(weakSelf) __weak __typeof(&*self)weakSelf = self;

在block之前定义:

WeakSelf(weakSelf);

所以在block中就不使用self,而改用weakSelf即可。

(13)关于(8)中提到的两个宏定义,定义时的位置一定要在#import头文件之前,如下所示:

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

我下面通过几个小例子来作为Masonry的入门:

【1】绘制一个红色的View,在屏幕中上下左右居中,宽高为200:

//绘制一个红色的View
- (void)setRedView
{WeakSelf(weakSelf);self.redView = [[UIView alloc] init];self.redView.backgroundColor = [UIColor redColor];//在设置Autolayout之前,要将view添加到self.view上面[self.view addSubview:self.redView];[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {make.center.mas_equalTo(weakSelf.view);make.size.mas_equalTo(CGSizeMake(200, 200));}];
}

注意:在对redView设置约束之前,一定要把它添加到self.view中!

【2】在红色的View中绘制一个灰色的View,主要学习如何使用复合属性和单一属性设置四周边距:

//在红色的View中绘制一个灰色的View
- (void)setGrayViewEdgeInsetToRedView
{WeakSelf(weakSelf);self.grayView = [[UIView alloc] init];self.grayView.backgroundColor = [UIColor grayColor];[self.redView addSubview:self.grayView];[self.grayView mas_makeConstraints:^(MASConstraintMaker *make) {//可以使用符合属性设置// make.edges.equalTo(weakSelf.redView).with.insets(UIEdgeInsetsMake(20, 20, 20, 20));//上述代码也可以拆分为://可以使用with对同一条约束设置参数//        make.top.equalTo(weakSelf.redView).with.offset(20);//        make.left.equalTo(weakSelf.redView).with.offset(20);//        make.bottom.equalTo(weakSelf.redView).with.offset(-20);//        make.right.equalTo(weakSelf.redView).with.offset(-20);// 也可以去掉withmake.top.equalTo(weakSelf.redView).offset(20);make.left.equalTo(weakSelf.redView).offset(20);make.bottom.equalTo(weakSelf.redView).offset(-20);make.right.equalTo(weakSelf.redView).offset(-20);}];
}

【3】在灰色View里面绘制两个等宽等间距的View,设置左右边距,相互之间的边距为15,同时自动计算他们的宽度:

//在灰色View里面绘制两个等宽等间距的View,设置左右边距、相互之间边距为15
- (void)setTwoViewInGrayView
{WeakSelf(weakSelf);UIView *subView1 = [[UIView alloc] init];UIView *subView2 = [[UIView alloc] init];subView1.backgroundColor = [UIColor orangeColor];subView2.backgroundColor = [UIColor blueColor];[self.grayView addSubview:subView1];[self.grayView addSubview:subView2];[subView1 mas_makeConstraints:^(MASConstraintMaker *make) {make.centerY.equalTo(weakSelf.grayView.mas_centerY);make.left.equalTo(weakSelf.grayView.mas_left).with.offset(15);make.right.equalTo(subView2.mas_left).with.offset(-15);//设置subView1的高度为grayView高度的0.5.make.height.equalTo(weakSelf.grayView).multipliedBy(0.5);make.width.equalTo(subView2.mas_width);}];[subView2 mas_makeConstraints:^(MASConstraintMaker *make) {make.centerY.equalTo(weakSelf.grayView.mas_centerY);make.left.equalTo(subView1.mas_right).with.offset(15);make.right.equalTo(weakSelf.grayView.mas_right).offset(-15);make.height.equalTo(weakSelf.grayView).multipliedBy(0.5);make.width.equalTo(subView1.mas_width);}];//以上的两个约束还有如下简化的写法[subView1 mas_remakeConstraints:^(MASConstraintMaker *make) {//设置subView1的centerY属性,如果后面的grayView的参数也是centerY的话,就可以省略make.centerY.equalTo(weakSelf.grayView);//因为默认也是想要和grayView的左边距对齐,所以可以省略mas_left;make.left.equalTo(weakSelf.grayView).with.offset(15);//下面的mas_left不能省略,因为前面的参数是right,当前后参数不一致时,不能省略后面的参数make.right.equalTo(subView2.mas_left).with.offset(-15);make.height.equalTo(weakSelf.grayView).multipliedBy(0.5);//可以省略下面subView2的width参数make.width.equalTo(subView2);}];[subView2 mas_remakeConstraints:^(MASConstraintMaker *make) {make.centerY.equalTo(weakSelf.grayView);make.left.equalTo(subView1.mas_right).with.offset(15);make.right.equalTo(weakSelf.grayView).offset(-15);make.height.equalTo(weakSelf.grayView).multipliedBy(0.5);make.width.equalTo(subView1);}];
}

【4】学习设置比例系数:我要绘制一个View,宽度是self.view的0.5倍再减少10,高度是self.view的0.2倍,距离self.view左边距10,上部紧贴红色View:

- (void)setMutiplierAndConstant
{WeakSelf(weakSelf);UIView *yellowView = [[UIView alloc] init];yellowView.backgroundColor = [UIColor yellowColor];[self.view addSubview:yellowView];[yellowView mas_makeConstraints:^(MASConstraintMaker *make) {make.width.equalTo(weakSelf.view.mas_width).offset(-10).multipliedBy(0.5);//根据公式,这里的-10就是constant.make.height.equalTo(weakSelf.view.mas_height).multipliedBy(0.2).offset(0);make.top.equalTo(weakSelf.redView.mas_bottom).multipliedBy(1).offset(0);make.left.equalTo(weakSelf.view.mas_left).multipliedBy(1).offset(10);}];
}

【5】使用mas_key属性,使冲突发生时Log日志变得清晰,如下代码是带有冲突的代码:

- (void)setViewWithKey
{UIView *firstView = [[UIView alloc] init];firstView.backgroundColor = [UIColor blackColor];[self.view addSubview:firstView];//这里使用mas_key参数self.view.mas_key = @"self.view";firstView.mas_key = @"firstView";//写一个冲突的约束[firstView mas_makeConstraints:^(MASConstraintMaker *make) {make.size.mas_equalTo(CGSizeMake(100, 100));make.left.offset(10);make.right.offset(-10);}];
}

如果不使用mas_key来标识两个View,那么Log打印如下:

 Probably at least one of the constraints in the following list is one you don't want.Try this:(1) look at each constraint and try to figure out which you don't expect;(2) find the code that added the unwanted constraint or constraints and fix it.("<MASLayoutConstraint:0x7fef6a6a5d80 UIView:0x7fef6a4289d0.width == 100>","<MASLayoutConstraint:0x7fef6a7161a0 UIView:0x7fef6a4289d0.left == UIView:0x7fef6a40b970.left + 10>","<MASLayoutConstraint:0x7fef6a7145e0 UIView:0x7fef6a4289d0.right == UIView:0x7fef6a40b970.right - 10>","<NSLayoutConstraint:0x7fef6a7ade60 UIView:0x7fef6a40b970.width == 320>")Will attempt to recover by breaking constraint<MASLayoutConstraint:0x7fef6a6a5d80 UIView:0x7fef6a4289d0.width == 100>

其中打印出的是View的地址,对于有多个View的时候,Log就很难读了。

当设置mas_key后,输入如下:

 Probably at least one of the constraints in the following list is one you don't want.Try this:(1) look at each constraint and try to figure out which you don't expect;(2) find the code that added the unwanted constraint or constraints and fix it.("<MASLayoutConstraint:0x7fbf23e3b0b0 UIView:firstView.width == 100>","<MASLayoutConstraint:0x7fbf23e58410 UIView:firstView.left == UIView:self.view.left + 10>","<MASLayoutConstraint:0x7fbf23e588d0 UIView:firstView.right == UIView:self.view.right - 10>","<NSLayoutConstraint:0x7fbf23e5a610 UIView:self.view.width == 320>")Will attempt to recover by breaking constraint<MASLayoutConstraint:0x7fbf23e3b0b0 UIView:firstView.width == 100>

对于有可能哪一个View出现的冲突,Log日志就很容易区别。

【6】使用上述(8)谈到的两个宏,使用Masonry时可以省略mas_前缀,下面的代码是去掉了mas_前缀的,也可以成功编译运行:

- (void)useShorthand
{UIView *firstView = [[UIView alloc] init];firstView.backgroundColor = [UIColor blackColor];[self.view addSubview:firstView];self.view.mas_key = @"self.view";firstView.mas_key = @"firstView";//写一个冲突的约束[firstView makeConstraints:^(MASConstraintMaker *make) {make.size.equalTo(CGSizeMake(100, 100));make.left.offset(10);make.right.offset(-10);}];}

我这里介绍的Masonry使用还只是一个入门使用,想要更熟练的使用,那么必须在实际项目中去运用它。当然最好的学习方式就是去阅读Masonry的源代码啦。

Autolayout第三方库Masonry的入门与实践相关推荐

  1. 第三方库Masonry自动布局AutoLayout使用

    布局: 1. 放在哪  坐标  CGPoint(x, y)    2. 有多大  尺寸  CGSize(width, height) 布局方式: 1.绝对布局(FrameLayout)也称 坐标布局 ...

  2. iOS代码实现布局(三)—用CocoaPods导入第三方库Masonry

    在之前的文章中用代码实现了控件和布局,但是控件的位置是直接用坐标指定的,不美观也不便于手机机型的适配性,因此要导入第三方库Masonry来控制控件的坐标. 目录 基于CocoaPods安装Masonr ...

  3. OpenGL第三方库:GLFW入门篇

    前言:GLFW是继GLUT,FreeGLUT之后,当前最新的用来创建OpenGL上下文,以及操作窗口的第三方库.官方网址为:http://www.glfw.org/. 错误处理机制:在使用GLFW之前 ...

  4. python第三方库引用_Python入门:如何使用第三方库

    1. 第三方库 Python相当于一个手机,第三方库相当于手机里各种各样的APP. 当我们想搭建网站时,可以选择功能全面的Django.轻量的Flask等web框架:当我们想做一个爬虫时,可以使用Sc ...

  5. ios开发之autolayout 第三方框架Masonry

    不管是是界面创建约束还是代码创建约束,苹果官方提供的方式都比较繁琐.所以出现了第三方框架. Masonry 在github地址如下: https://github.com/SnapKit/Masonr ...

  6. 转帖Masonry介绍与使用实践(快速上手Autolayout)

    前言 1 MagicNumber -> autoresizingMask -> autolayout 以上是纯手写代码所经历的关于页面布局的三个时期 在iphone1-iphone3gs时 ...

  7. iOS 第三方框架-Masonry介绍与使用实践

    前言 MagicNumber -> autoresizingMask -> autolayout 以下是纯手写代码所经历的关于页面布局的三个时期 在iphone1-iphone3gs时代 ...

  8. Masonry介绍与使用实践:快速上手Autolayout

    今天看到的就转过来以防以后有需要,http://www.cocoachina.com/ios/20141219/10702.html 前言 1 MagicNumber -> autoresizi ...

  9. iOS Masonry介绍与使用实践(快速上手Autolayout)

    前言 MagicNumber -> autoresizingMask -> autolayout 以上是纯手写代码所经历的关于页面布局的三个时期 在iphone1-iphone3gs时代 ...

最新文章

  1. mysql date_format 按不同时间单位进行分组统计
  2. 计算机组成原理(哈工大刘宏伟)135讲(三)
  3. Mybatis笔记一:java.lang.NoClassDefFoundError: org/apache/ibatis/mapping/DatabaseIdProvider
  4. Druid 常见问题
  5. 【数据结构】线性表的顺序存储结构(c语言实现)
  6. 专题:区块链与数据共享(下)
  7. SQL中 Left Join 与 Right Join 与 Inner Join 与 Full Join的区别
  8. 大型企业网络构建之网关冗余
  9. SHELL下根据进程号得到内存,并截取为整数
  10. 国家科技管理信息系统构建及其对科技情报工作的影响
  11. 计算机桌面时间设置,桌面的时钟怎么设置
  12. 利用腾讯云函数搭建免费代理池
  13. tomcat 服务器无响应,关于tomcat:数据库连接池连接耗尽导致tomcat请求无响应呈现出假死状态...
  14. BERT知识点汇总(en cour...)
  15. 平安京因服务器升级维护无法,《阴阳师》手游12月31日维护更新公告
  16. java实现Word文档(doc、docx)在线查看功能(前台+后台)
  17. 使用clipboard.js实现复制内容至剪贴板
  18. 市场调研-全球与中国沉鱼饲料市场现状及未来发展趋势
  19. java中length,length()和size()各自含义
  20. git + 码云 使用详解(入门)(mac+windows教程)

热门文章

  1. 【转载】一封写给有忧国忧民症状的幼稚知识分子的信
  2. Surface Pro 4安装Ubuntu
  3. Python爬虫学习笔记_DAY_3_Python类型查询与类型转换【Python爬虫】
  4. IEEE 802.15.4的信道接入机制二信标网络中的CSMA-CA算法
  5. 英语高考计算机阅读答案解析,2021考研英语一阅读理解试题及答案解析(中公考研版)...
  6. iOS WKUserContentController
  7. Ngrok 实现内网穿透教程(Ngrok 和 Sunny-Ngrok )
  8. Python养发之路 - 安装篇
  9. gif动图制作方法一
  10. 盘点个人信息保护方面的那些认证