美文网首页GXiOS
iOS开发之Masonry

iOS开发之Masonry

作者: 简单Timor | 来源:发表于2018-11-14 10:49 被阅读65次

简介

Masonry 就是第三方为我们封装好的一个 AutoLayout 框架。其使用点语法,可以非常便利的添加 AutoLayout约束,且通俗的语法让人非常容易理解。

集成方式

Masonry 支持 CocoaPods,可以直接通过 podfile 文件进行集成,需要在 CocoaPods 中添加下面代码:

pod 'Masonry'
Masonry使用前注意:

1.在使用Masonry添加约束之前,需要在addSubview方法之后才能使用,否则会导致崩溃。
2.在添加约束时初学者经常会出现一些错误,约束出现问题的原因一般就是两种:约束冲突和缺少约束。对于这两种问题,可以通过调试log排查。
3.之前使用 Interface Builder 添加约束,如果约束有错误直接就可以看出来,并且会以红色或者黄色警告体现出来。而 Masonry 则不会直观的体现出来,而是以运行过程中崩溃或者打印异常log体现,所以这也是手写代码进行 AutoLayout 的一个缺点。这个问题只能通过多敲代码,积攒纯代码进行 AutoLayout 的经验,慢慢就用起来越来越得心应手了。

基础语法

Masonry的基础API如下所示:
mas_makeConstraints()    //添加约束
mas_remakeConstraints()  //移除之前的约束,重新添加新的约束
mas_updateConstraints()  //更新约束
equalTo()       //参数是对象类型,一般是视图对象或者 mas_width 这样的坐标系对象
mas_equalTo()   //和上面功能相同,参数可以传递基础数据类型对象,可以理解为比上面的API更强大
width()         //用来表示宽度,例如代表view的宽度
mas_width()     //用来获取宽度的值。和上面的区别在于,一个代表某个坐标系对象,一个用来获取坐标系对象的值

其基础的设置属性如下:

1.尺寸:width、height、size。
2.边界:left、leading、right、trailing、top、bottom、edges。
3.中心点:center、centerX、centerY。
4.偏移量:offset、insets、sizeOffset、centerOffset。
5.priority()约束优先级(0~1000),multipler乘因数,dividedBy除因数。

大小关系有三种:

1.equalTo,相等。
2.lessThanOrEqualTo,小于等于。
3.greaterThanOrEqualTo,大于等于。

Auto Boxing

上面例如equalTo或者width这样的,有时候需要涉及到使用mas_前缀,这在开发中需要注意作区分。
如果在当前类引入#import "Masonry.h"之前,用下面两种宏定义声明一下,就不需要区分mas_前缀。

// 定义这个常量,就可以不用在开发过程中使用mas_前缀。
#define MAS_SHORTHAND
// 定义这个常量,就可以让Masonry帮我们自动把基础数据类型的数据,自动装箱为对象类型。
#define MAS_SHORTHAND_GLOBALS
修饰语

Masonry为了让代码使用和阅读更容易理解,所以直接通过点语法就可以调用,还添加了andwith两个方法。这两个方法内部实际上什么都没干,只是在内部将self直接返回,功能就是为了更加方便阅读,对代码执行没有实际作用。
例如下面的例子:

make.top.and.bottom.equalTo(self.containerView).with.offset(padding);

其内部代码实现,实际上就是直接将self返回。

- (MASConstraint *)with {
    return self;
}
添加约束

设置Size

// 我们先简单创建一个UIView视图。
UIView *view = [[UIView alloc] init];
view.backgroundColor =  [UIColor redColor];
    
// 要在加入视图之后再设置它的约束。
[self.view addSubview:view];
    
// 使用Masonry添加约束。
[view makeConstraints:^(MASConstraintMaker *make) {
    // 设置宽度和高度为100
    // euqalTo(@100),这里不用mas前缀的话,参数要加@.
    // 如果我们想要直接使用数字的话,Masonry提供了mas_前缀。
    // 这个前缀会自动将基础数据类型转换为NSNumber类型。
    // 这个过程叫做封箱(Auto Boxing)。
    // "mas_xx"开头的宏定义,内部都是通过MASBoxValue()函数实现的。
    // 这样的宏定义主要有四个,分别是mas_equalTo()、mas_offset()和大于等于、小于等于四个。
    // 不过因为引用了开头两个宏定义。所以这里应该不加也没事。
    make.width.and.height.equalTo(100);
}];

就如上面我们所介绍的,mas_makeConstraints() 是添加约束的方法,其参数是一个block代码块,我们在代码块中添加约束。

倍数

我们可以设置子视图为父视图某个参数的多少多少倍,这在 Masonry 中我们使用 multipliedBy就可以做到:

[view makeConstraints:^(MASConstraintMaker *make) {
    // multipliedBy设置系数。为父视图的一半。
    make.size.equalTo(self.view).multipliedBy(0.5);
}];
中心点

我们可以直接设置视图的center等于其他视图,来达到水平剧中的目的。

[view makeConstraints:^(MASConstraintMaker *make) {
    // 中心和视图的中心对齐。
    make.center.equalTo(self.view);
    // 相当于下面这两句
    // self.view.mas_centerX这句话可以直接写self.view
    make.centerX.equalTo(self.view.centerX);
    make.centerY.equalTo(self.view.centerY);
    }];
边距
[view makeConstraints:^(MASConstraintMaker *make) {
    // 设置四周的边距。如果还设置了宽度和高度,则边距只有左和上生效。
    // 这里参数不能直接写数值了。不过这里不用区分正负。
    // insets不用区分正负,可以四个边距一起设置,但是缺点是写的稍微有点长
    // offset区分正负,如果4个边距用offset(10)的话,右下两个边距就会出问题
    make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(50, 50, 50, 50));
    // 如果边距分开设置的话,就需要区分正负了。但是可以直接写数值。
    make.left.and.top.equalTo(self.view).offset(50);
    make.right.and.bottom.equalTo(self.view).offset(-50);
    }];
优先级
/** 
 Masonry为我们提供了三个默认的方法,priorityLow()、priorityMedium()、priorityHigh(),这三个方法内部对应着不同的默认优先级。
 除了这三个方法,我们也可以自己设置优先级的值,可以通过priority()方法来设置。
 */
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.center.equalTo(self.view);
    make.width.equalTo(self.view).priorityLow();
    make.width.mas_equalTo(20).priorityHigh();
    make.height.equalTo(self.view).priority(200);
    make.height.mas_equalTo(100).priority(1000);
}];
更新约束

关于更新约束,Masonry提供给我们如下两个方法:

[控件 mas_remakeConstraints:^(MASConstraintMaker *make) {
//这个方法会将以前的约束全部删除,添加新的约束
}];
[控件 mas_updateConstraints:^(MASConstraintMaker *make) {
//这个方法将会覆盖以前的某些特定的约束
}];

我们这里用第二个方法举个例子:

// GCD方法,在显示出来两秒之后执行block代码
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    
    // updateConstraints更新约束。这个方法将会覆盖以前的某些特定的约束
    [view updateConstraints:^(MASConstraintMaker *make) {
        
        // 在updateConstraints里,如果原先的size是有multipliedBy的,那么重新添加的size约束会有问题。
        // 如果原先的size约束没有multipliedBy,那么给size再添加multipliedBy不会出问题。
       
        // 这里如果给比0.5小的值,它就会消失。
        // 如果给0.5大的值,就没有任何效果。
        make.size.equalTo(self.view).multipliedBy(0.3);
        
        // 如果原先是直接写值的话,这里就没问题,可以变大也可以变小。
        // 结论,并不是只能往小里面改变。应该是multipliedBy的问题。
        make.size.equalTo(50);
        
        // 不会覆盖四个边距。只会覆盖原先的center约束。
        make.center.equalTo(self.view);
    }];
});

从上面我们可以发现,mas_updateConstraints()只会更新与其对应的约束,而center可不算边界约束哦,它应该只会覆盖对应的center约束,而不会覆盖left之类的边界约束。

使用示例

UILabel *testLabel = [[UILabel alloc] init];
[self.view addSubview:testLabel];
/*
* 为Label设置约束。
* 现在Label可以在约束范围内自适应它内容的高度和宽度
*/
[testLabel makeConstraints:^(MASConstraintMaker *make) {
    make.center.equalTo(self.view);
    // 宽度小于等于200。
    make.width.lessThanOrEqualTo(200);
    // 高度大于等于100。
    make.height.greaterThanOrEqualTo(100);
}];
testLabel.text = @"这是测试的字符串。能看到1、2、3个步骤,第一步当然是上传照片了,要上传正面近照哦。上传后,网站会自动识别你的面部,如果觉得识别的不准,你还可以手动修改一下。左边可以看到16项修改参数,最上面是整体修改,你也可以根据自己的意愿单独修改某项,将鼠标放到选项上面,右边的预览图会显示相应的位置。";
// 想要自适应Lable的Size的话一定要加这一行。否则没有效果。
testLabel.numberOfLines = 0;
三个等高视图

下面的例子是通过给equalTo()方法传入一个数组,设置数组中子视图及当前make对应的视图之间等高。

UIView *redView = [[UIView alloc] init];
redView.backgroundColor =  [UIColor redColor];
UIView *greenView = [[UIView alloc] init];
greenView.backgroundColor =  [UIColor greenColor];
UIView *yellowView = [[UIView alloc] init];
yellowView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:redView];
[self.view addSubview:greenView];
[self.view addSubview:yellowView];
CGFloat padding = 10.0f;
[redView makeConstraints:^(MASConstraintMaker *make) {
    // 这种样子的写法也可以。
    make.top.and.left.and.right.equalTo(self.view).insets(UIEdgeInsetsMake(padding, padding, 0, padding));
    
    // 这个地方要给greenView的top值。不给不行。
    make.bottom.equalTo(greenView.top).offset(-padding);
}];
[greenView makeConstraints:^(MASConstraintMaker *make) {
    
    // 设置左右间距
    make.left.and.right.equalTo(self.view).offset(padding);
    
    // 设置下间距
    make.bottom.equalTo(yellowView.top).offset(-padding);
}];
[yellowView makeConstraints:^(MASConstraintMaker *make) {
    
    // 设置左右以及下边距。
    make.bottom.and.left.and.right.equalTo(self.view).insets(UIEdgeInsetsMake(0, padding, padding, padding));
    
    // 三个视图高度相等。
    make.height.equalTo(@[redView, greenView]);
}];
相对父视图垂直居中

效果:

两个子视图宽度相等,相对水平居中。
两个子视图左右间距各为10,中间间距为10.
两个子视图高度固定为150.
两个子视图整体相对于父视图垂直居中。
代码如下:

 UIView *redView = [[UIView alloc] init];
    redView.backgroundColor =  [UIColor redColor];
    
    UIView *greenView = [[UIView alloc] init];
    greenView.backgroundColor =  [UIColor greenColor];
    
    [self.view addSubview:redView];
    [self.view addSubview:greenView];
    
    CGFloat padding = 10.0f;
    
    [redView makeConstraints:^(MASConstraintMaker *make) {
        // 设置高度为固定150.
        make.height.equalTo(150);
        // 设置宽度
        make.width.equalTo(greenView);
        // 设置垂直居中对齐。
        make.centerY.equalTo(self.view);
        // 设置左间距
        make.left.equalTo(self.view).offset(padding);
        // 设置右间距
        make.right.equalTo(greenView.left).offset(-padding);
    }];
    
    [greenView makeConstraints:^(MASConstraintMaker *make) {
        // 设置高度为固定150.
        make.height.equalTo(150);
        // 设置宽度
        make.width.equalTo(redView);
        // 设置垂直居中对齐。
        // 下面这两句代码都可以。一个是设置水center的Y值和self.view相等,一个是和redView相等。
        make.centerY.equalTo(self.view);
//        make.centerY.equalTo(redView);
        // 设置右间距
        make.right.equalTo(self.view).offset(-padding);
    }];

如上可以想到,如果需要设置两个子视图垂直居中,且相对父视图整体水平居中的话。我们可以改为设置两个子视图的centerX值和父视图相等,然后设置其上下间距。

参考:iOS开发之Masonry的基础用法

`

相关文章

  • Masonry

    iOS开发之Masonry框架源码解析

  • iOS开发 Masonry简介

    iOS开发 Masonry简介 传送门:https://github.com/SnapKit/Masonry

  • iOS开发之Masonry

    简介 Masonry 就是第三方为我们封装好的一个 AutoLayout 框架。其使用点语法,可以非常便利的添加 ...

  • Masonry框架源码分析

    Masonry框架源码分析 相信大多数iOS开发者对Masonry框架并不陌生 , 本文是笔者通读Masonry的...

  • Masonry

    Masonry介绍与使用实践 - iOS移动开发周报 - 推酷

  • Masonry布局框架简单的介绍和使用。

    Masonry(自动布局)的基本使用 Masonry的基本介绍 在iOS开发中,为了满足开发者对苹果手机屏幕进行一...

  • iOS masonry九宫格 单行 多行布局

    iOS masonry九宫格 单行 多行布局 Masonry是个好东西,在当前尺寸各异的iOS开发适配中发挥着至关...

  • iOS Masonry

    Masonry Masonry是iOS推出autolayout之后出现的一个开源框架,方便开发者指定view的相对...

  • ##iOS开发之ReactiveCocoa(基础)

    iOS开发之ReactiveCocoa(一) 前言 前段时间在看Masonry这个全新的第三方的布局框架的时候,开...

  • Masonry 宏定义的尴尬

    引言 Masonry在 iOS 开发界的名气相信不用多做介绍了, 大部分开发者在使用Masonry的过程中都会导...

网友评论

    本文标题:iOS开发之Masonry

    本文链接:https://www.haomeiwen.com/subject/fvjdfqtx.html