Masonry

发布于:2025-09-04 ⋅ 阅读:(16) ⋅ 点赞:(0)

前言

Masonry是iOS上一个轻量级的Auto Layout 框架。可以使用链式语法写布局,比原生NSLayoutConstraint简介很多。这里读者就学习的Masonry内容作个总结。

链式语法:允许在同一条语句中连续调用多个方法,每个方法返回对象自身。

Masonry使用

核心方法

Masonry在使用时有三大核心方法:

  • mas_makeConstraints:创建约束。第一次给控件添加约束时使用。
  • mas_updateConstraints:更新约束。控件尺寸位置发生变化时,只修改block中的约束来更新部分约束而不影响其他布局。
  • mas_remakeConstraints:移除约束。在需要彻底重新布局时(从竖屏切换成横屏),移除先前所有约束,然后添加新约束。

写法示例

这里展示两种写法:

  • 指定依赖的视图
#import "ViewController.h"
#import <Masonry/Masonry.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor greenColor];
    [self.view addSubview:view];
    
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(self.view.mas_left).mas_offset(50);
            //等同于make.left.equalTo(self.view).with.offset(50);
            make.right.mas_equalTo(self.view.mas_right).mas_offset(-50);
            make.top.mas_equalTo(self.view.mas_top).mas_offset(100);
            make.bottom.mas_equalTo(self.view.mas_bottom).mas_offset(-100);
    }];
  
}

@end
  • 直接传值

这种写法等同于相对父视图的约束加偏移量,适合父子视图的简单布局。

[view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(50);
            make.right.mas_equalTo(-50);
            make.top.mas_equalTo(100);
            make.bottom.mas_equalTo(-100);
    }];

请添加图片描述

总结一下,上述第一种写法适用于复杂的UI,而第二种简单快捷,只用于简单的父子关系的视图。

这里补充两个我在练习demo时遇到的问题:

  • .xcworkspace 🆚 .xcodeproj
    • .xcworkspace:是一个Xcode基础工程文件
    • .xcodeproj:是工作区文件,可以把多个.xcworkspace项目融合在一起,即将主工程和第三方依赖工程组合在一起

因而我们在导入第三方库后,我们的项目代码应该从.xcodeproj打开进行编辑

  • #import “Masonry.h” 🆚 #import <Masonry/Masonry.h>
    • #import “Masonry.h”:Xcode会现在当前工程目录中查找头文件,找不到后再去Pods路径查找
    • #import <Masonry/Masonry.h>:表示到全局文件去搜索路径,也就是直接通过Pods搜索路径找到

CocoaPods 现在默认使用 #import <Masonry/Masonry.h>

具体示例

在上面简单的布局上,我们进行一个升级来使用Masonry来实现布局:

self.fatherView = [[UIView alloc] init];
self.fatherView.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.fatherView];

[self.fatherView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.mas_equalTo(50);
    make.right.mas_equalTo(-50);
    make.top.mas_equalTo(100);
    make.bottom.mas_equalTo(-100);
}];

self.sonView = [[UIView alloc] init];
self.sonView.backgroundColor = [UIColor grayColor];
[self.fatherView addSubview:self.sonView];

[self.sonView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.mas_equalTo(50);
    make.right.mas_equalTo(-50);
    make.top.mas_equalTo(50);
    make.bottom.mas_equalTo(-50);
}];

//居中布局
//    [self.sonView mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.center.mas_equalTo(0);
//        make.height.mas_equalTo(50);
//        make.width.mas_equalTo(50);
//    }];

UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(20, 20, 50, 50);
btn.backgroundColor = [UIColor blackColor];
[btn addTarget:self action:@selector(pressBtn) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];

-(void)pressBtn {
    [self.fatherView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(30);
        make.right.mas_equalTo(-30);
        make.top.mas_equalTo(60);
        make.bottom.mas_equalTo(-60);
    }];
    
    [self.sonView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(10);
        make.right.mas_equalTo(-10);
        make.top.mas_equalTo(10);
        make.bottom.mas_equalTo(-10);
    }];
}

展示一下效果:

在这里插入图片描述

Masonry使用原因

上面我们学习了Masonry的简单使用方法后也能明显的看出放弃传统的AutoLayout布局的原因,即通过链式调用的方式来描述布局,使得排版代码更加简洁易读。

这里展示一下传统的AutoLayout布局来进一步体现代码上的区别:

  • 传统 Auto Layout

系统给的自动布局API笔者都通过注释的方式体现在了代码中。

UIView *view = [[UIView alloc] init];
view.backgroundColor = [UIColor greenColor];
[self.view addSubview:view];

//关闭Autoresizing转换为Auto Layout
[view setTranslatesAutoresizingMaskIntoConstraints:NO];

//宽高约束
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:view//约束视图
                                       attribute:NSLayoutAttributeWidth//约束视图的属性
                                       relatedBy:NSLayoutRelationEqual//枚举值
                                       //NSLayoutRelationEqual:等于
                                       //NSLayoutRelationLessThanOrEqual:小于等于
                                       //NSLayoutRelationGreaterThanOrEqual:大于等于
                                       toItem:nil//参考视图
                                       attribute:NSLayoutAttributeNotAnAttribute//参考视图属性
                                                                  multiplier:1//约束视图和参考视图比例
                                                                    constant:100];//约束值额外偏移量

NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:view
                                                                    attribute:NSLayoutAttributeHeight
                                                                    relatedBy:NSLayoutRelationEqual
                                                                       toItem:nil
                                                                    attribute:NSLayoutAttributeNotAnAttribute
                                                                   multiplier:1
                                                                     constant:100];
[view addConstraint:widthConstraint];
[view addConstraint:heightConstraint];

//水平垂直约束
NSLayoutConstraint *centerX = [NSLayoutConstraint constraintWithItem:view
                                                           attribute:NSLayoutAttributeCenterX
                                                           relatedBy:NSLayoutRelationEqual
                                                              toItem:self.view
                                                           attribute:NSLayoutAttributeCenterX
                                                          multiplier:1
                                                            constant:0];
NSLayoutConstraint *centerY = [NSLayoutConstraint constraintWithItem:view
                                                           attribute:NSLayoutAttributeCenterY
                                                           relatedBy:NSLayoutRelationEqual
                                                              toItem:self.view
                                                           attribute:NSLayoutAttributeCenterY
                                                          multiplier:1
                                                            constant:0];

[self.view addConstraint:centerX];
[self.view addConstraint:centerY];

Masonry约束优先级

优先级是用于处理发生冲突的约束布局的。

这是设置Masonry约束优先级的基础方法:

[self.fatherView mas_makeConstraints:^(MASConstraintMaker *make) {
  make.width.mas_equalTo(200).priorityHigh();//高优先级
  make.height.mas_equalTo(100).priorityLow();//低优先级
  make.width.mas_equalTo(200).priorityMedium();//中等优先级
}];

除此之外,还可以自定义数值来表示优先级,如果像上面的默认不设置时,就是1000,表示必须满足。

make.width.mas_equalTo(200).priority(600);

通过具体例子展示一下

UIView *view1 = [[UIView alloc] init];
view1.backgroundColor = [UIColor greenColor];
[self.view addSubview:view1];

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(self.view.mas_left).mas_offset(50);
        make.right.mas_equalTo(self.view.mas_right).mas_offset(-50);
        make.top.mas_equalTo(self.view.mas_top).mas_offset(500);
        make.bottom.mas_equalTo(self.view.mas_bottom).mas_offset(-100);
}];


UIView *view2 = [[UIView alloc] init];
view2.backgroundColor = [UIColor yellowColor];
[self.view addSubview:view2];

[view2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(self.view.mas_left).mas_offset(50);
        make.right.mas_equalTo(self.view.mas_right).mas_offset(-50);
        make.top.mas_equalTo(self.view.mas_top).mas_offset(100);
        make.bottom.mas_equalTo(self.view.mas_bottom).mas_offset(-400);
}];

UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = [UIColor blackColor];
[self.view addSubview:btn];

[btn mas_makeConstraints:^(MASConstraintMaker *make) {
    make.center.equalTo(view1).priorityLow();
    make.center.equalTo(view2).priorityHigh();
}];

在这里插入图片描述

可以看的出来,因为优先级的设置,按钮显示到了view2上,如果没有优先级设置,按钮会按照代码顺序显示在view1上。

总结

以上就是我对Masonry的学习总结,在今后的学习中将会多练习使用Cocoapods导入第三方库和Masonry布局来提高我的代码性能。