什么是Masonry
Masonry是一个对原生NSLayoutConstraint布局进行封装的第三方自动布局框架,采用链式编程法给开发者提供接口。相比系统原生自动布局来说,Masonry的布局功能是有过之而无不及。
另外Masonry是同时支持Mac和iOS平台的,在这两个平台上都可以使用Masonry进行自动布局。
Masonry布局初体验
在介绍NSLayoutConstraint布局时,有个示例是布局一个简单的View(top:50,left:50,width:150,height:150)。现在改用Masonry实现之。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
UIView *layoutView = [[UIView alloc]init];
// Masonry内部会主动添上这句,所以这里不用加
// layoutView.translatesAutoresizingMaskIntoConstraints = NO;
layoutView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:layoutView];
[layoutView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_offset(50.0);
make.left.mas_offset(50.0);
make.height.mas_equalTo(150.0);
make.width.mas_equalTo(150.0);
}];
// // top和left以及width和heigth相同,可以进一步简写
// [layoutView mas_makeConstraints:^(MASConstraintMaker *make) {
// make.top.left.mas_offset(50.0);
// make.height.width.mas_equalTo(150.0);
// }];
}
Masonry采取链式编程的方式,让代码非常清晰易懂,而且代码量非常少。之前用原生方式写很多代码才能实现的布局,用Masonry几行代码就可以搞定。
Masonry布局示例
这里我不打算讲Masonry 的框架实现方式,因为有很多大佬已经分析的很清楚,并且这些资料也很容易获取。建议没有看过源码的,尽量去看下,搞懂链式编程法对自己的提升还是很大的。这里我想用Masonry实现左右两个Label宽高不固定的布局。
布局需求:
- 横向:leftLabel的宽度由其内容确定(内容不会超出屏幕宽度);rightLabel的左边距离leftLabel的右边为10。
- 纵向:两个label均居中,且高度相同;rightLabel可能会有多行。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor lightGrayColor];;
UILabel *leftLabel = [[UILabel alloc]init];
leftLabel.numberOfLines = 1;
leftLabel.backgroundColor = [UIColor purpleColor];
// 设置抗拉伸级,即label不可被拉伸
[leftLabel setContentHuggingPriority:(UILayoutPriorityRequired) forAxis:(UILayoutConstraintAxisHorizontal)];
// 设置抗压缩级,即label不可被压缩
[leftLabel setContentCompressionResistancePriority:(UILayoutPriorityRequired) forAxis:(UILayoutConstraintAxisHorizontal)];
UILabel *rightLabel = [[UILabel alloc]init];
rightLabel.numberOfLines = 0;
rightLabel.backgroundColor = [UIColor magentaColor];
[self.view addSubview:leftLabel];
[self.view addSubview:rightLabel];
leftLabel.text = @"名剑无名倦收天";
rightLabel.text = @"江天一色无纤尘,鱼龙潜跃观道身。天人焉有两般义,道不虚行只在人。";
[leftLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_offset(0);
make.left.mas_offset(0);
make.height.equalTo(rightLabel);
}];
[rightLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(leftLabel);
make.left.equalTo(leftLabel.mas_right).mas_offset(10.0);
make.right.mas_offset(0);
}];
}
布局效果见下图:
说明
Apple在iOS11提出了布局安全域的概念,Masonry也同步进行了适配。特别是碰到刘海屏的时候,要加以考虑。
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
if (@available(iOS 11.0,*)) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
make.left.equalTo(self.view.mas_safeAreaLayoutGuideLeft);
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
make.right.equalTo(self.view.mas_safeAreaLayoutGuideRight);
} else {
make.edges.mas_offset(0);
}
}];
如果考虑导航栏以及选项卡控制器,最好写成下面这样:
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
if (@available(iOS 11.0,*)) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
make.left.equalTo(self.view.mas_safeAreaLayoutGuideLeft);
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
make.right.equalTo(self.view.mas_safeAreaLayoutGuideRight);
} else {
make.top.equalTo(self.mas_topLayoutGuide);
make.bottom.equalTo(self.mas_bottomLayoutGuide);
make.left.right.mas_offset(0);
}
}];