什么是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);
}];
}
布局效果見下圖:
image.png
說明
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);
}
}];