簡(jiǎn)介
本文主要是針對(duì)UIScrollView利用Masonry框架來自動(dòng)布局,因?yàn)閁IScrollView可以滑動(dòng),所以本身布局跟一般的UIView不太一樣,然后樓主之前面試的時(shí)候也有人問過樓主這個(gè)問題,所以樓主想簡(jiǎn)單總結(jié)一下方便你我他它。關(guān)于Masonry這個(gè)框架,相信大家也都在用它,可以去github上面下載,它里面的各種demo也是非常有用的。
我們?cè)O(shè)置約束用到的幾個(gè)方法簡(jiǎn)單介紹:
一.mas_makeConstraints
:設(shè)置約束,如果你的視圖不需要根據(jù)什么情況更新約束,只需要設(shè)置一次的話,請(qǐng)使用它。
錯(cuò)誤示范:多次調(diào)用
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.scrollView];
[self.scrollView addSubview:self.containerView];
[self.containerView addSubview:self.testButton];
[self.containerView addSubview:self.testView];
// 設(shè)置約束
[self setupConstraints];
}
- (void)setupConstraints {
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view).offset(64);
make.left.right.bottom.equalTo(self.view);
}];
[self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.scrollView);
make.width.equalTo(self.scrollView);
}];
[self.testButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.containerView).offset(100);
make.left.equalTo(self.containerView).offset(50);
make.right.equalTo(self.containerView).offset(-50);
make.height.equalTo(@40);
}];
[self.testView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.testButton.mas_bottom).offset(200);
make.left.right.equalTo(self.containerView);
make.height.equalTo(@400);
make.bottom.equalTo(self.containerView);
}];
}
- (void)testButtonClick {
[self setupConstraints];
}
結(jié)果:
第一次添加約束時(shí),約束數(shù)組是醬紫的:
這時(shí)候約束數(shù)組的count為0,是正確的,因?yàn)槲覀冎皼]有設(shè)置過約束,點(diǎn)擊測(cè)試按鈕,再添加一次約束,結(jié)果是醬紫的:
這時(shí)候,約束數(shù)組的count值是4,也是正確的,因?yàn)槲覀兲砑舆^一次了,可是這次點(diǎn)擊過后,約束數(shù)組的count就會(huì)變成8了:
很明顯,點(diǎn)擊一次就會(huì)重復(fù)累加而不會(huì)清除之前的約束,后果可想而知。。。說到這里,大家應(yīng)該理解mas_makeConstraints
的使用場(chǎng)景了。
二.mas_updateConstraints
:更新約束,如果你的布局需要根據(jù)具體情況來更新子控件的約束,那么請(qǐng)使用它。mas_updateConstraints
是對(duì)比該對(duì)象之前的約束數(shù)組,添加過的約束就直接修改它的值,沒有添加過的約束就添加上。
結(jié)論:無論你點(diǎn)多少次都不重復(fù)添加約束,感覺
mas_updateConstraints
真是棒棒噠。
三.mas_remakeConstraints
:在mas_makeConstraints
的基礎(chǔ)上會(huì)清除掉之前所有的約束,再重新添加新的約束。
UIScrollView的自動(dòng)布局問題
在利用自動(dòng)布局來布局UIScrollView時(shí),一般都會(huì)在上面添加一個(gè)UIView的子控件,來正確布局:
代碼片段
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.scrollView];
[self.scrollView addSubview:self.containerView];
[self.containerView addSubview:self.testButton];
[self.containerView addSubview:self.testView];
[self.view setNeedsUpdateConstraints];
}
- (void)updateViewConstraints {
[self.scrollView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view).offset(64);
make.left.right.bottom.equalTo(self.view);
}];
[self.containerView mas_updateConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.scrollView);
// 確定containerView的寬度
make.width.equalTo(self.scrollView);
}];
[self.testButton mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.containerView).offset(100);
make.left.equalTo(self.containerView).offset(50);
make.right.equalTo(self.containerView).offset(-50);
make.height.equalTo(@40);
}];
[self.testView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.testButton.mas_bottom).offset(200);
make.left.right.equalTo(self.containerView);
make.height.equalTo(@400);
// 確定containerView的高度
make.bottom.equalTo(self.containerView);
}];
// 必須要調(diào)用
[super updateViewConstraints];
}
scrollView的contentSize要根據(jù)containerView的高度來設(shè)置,containView的高度又要根據(jù)它內(nèi)部的子控件來設(shè)置,make.bottom.equalTo(self.containerView)
確定containerView的高度,make.width.equalTo(self.scrollView)
確定containerview的寬度。
模擬復(fù)雜環(huán)境下UISCrollView的自動(dòng)布局
現(xiàn)假如有這么一種需求:一個(gè)控制器里面有多個(gè)視圖A B C D,而每個(gè)視圖的內(nèi)容要去請(qǐng)求網(wǎng)絡(luò)獲取數(shù)據(jù)才能確定高度,但是對(duì)于這幾個(gè)網(wǎng)絡(luò)請(qǐng)求誰先成功獲取數(shù)據(jù)計(jì)算到高度是不確定的,如何布局?
代碼片段
#pragma mark -- life cycle
- (void)viewDidLoad {
[super viewDidLoad];
self.oneHeight = 0;
self.twoHeight = 0;
self.threeHeight = 0;
self.fourHeight = 0;
[self.view addSubview:self.scrollView];
[self.scrollView addSubview:self.containerView];
[self.containerView addSubview:self.oneLabel];
[self.containerView addSubview:self.twoLabel];
[self.containerView addSubview:self.threeLabel];
[self.containerView addSubview:self.fourLabel];
[self.view setNeedsUpdateConstraints];
// 模擬3s后網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)回來了,oneLabel根據(jù)數(shù)據(jù)獲得了高度。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.oneHeight = 80;
[self.view setNeedsUpdateConstraints];
});
// 模擬6s后網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)回來了,fourLabel根據(jù)數(shù)據(jù)獲得了高度。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.fourHeight = 100;
[self.view setNeedsUpdateConstraints];
});
// 模擬9s后網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)回來了,twoLabel根據(jù)數(shù)據(jù)獲得了高度。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(9 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.twoHeight = 150;
[self.view setNeedsUpdateConstraints];
});
// 模擬12s后網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)回來了,threeLabel根據(jù)數(shù)據(jù)獲得了高度。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(12 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.threeHeight = 60;
[self.view setNeedsUpdateConstraints];
});
}
- (void)updateViewConstraints {
[self.scrollView mas_updateConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
[self.containerView mas_updateConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.scrollView);
make.width.equalTo(self.scrollView);
}];
[self.oneLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.containerView).offset(50);
make.left.right.equalTo(self.containerView);
make.height.equalTo(@(self.oneHeight));
}];
[self.twoLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.oneLabel.mas_bottom);
make.left.right.equalTo(self.containerView);
make.height.equalTo(@(self.twoHeight));
}];
[self.threeLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.twoLabel.mas_bottom);
make.left.right.equalTo(self.containerView);
make.height.equalTo(@(self.threeHeight));
}];
[self.fourLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.threeLabel.mas_bottom);
make.left.right.equalTo(self.containerView);
make.height.equalTo(@(self.fourHeight));
make.bottom.equalTo(self.containerView);
}];
[super updateViewConstraints];
}
結(jié)果:樓主做的這個(gè)gif圖跟實(shí)際有點(diǎn)差別,將就看