TIPS: 如有錯誤之處歡迎批評指正
使用Masonry,通過代碼來進(jìn)行布局
- equalto 和 mas_equalto 是有區(qū)別的窖式。但是我們不打算去了解蚁飒,可以通過添加以下代碼來統(tǒng)一。
- 注意B艽拆吆! 宏定義必須要放在
import
引入頭文件之前实抡!
- 注意B艽拆吆! 宏定義必須要放在
//define this constant if you want to use Masonry without the 'mas_' prefix
#define MAS_SHORTHAND
//define this constant if you want to enable auto-boxing for default syntax
#define MAS_SHORTHAND_GLOBALS
#import "Masonry.h"
-
使用masonry的步驟及注意點熏版。先來看下面這段代碼
- 進(jìn)行約束的 self.SelChildView必須已經(jīng)被addView添加過咖驮。也就是說必須已經(jīng)有父類了,否則報錯
-
make.top .bottom .left .right .等等方向equalTo后面()的內(nèi)容
mv.openDrawerButton.bottom
,必須用mv.openDrawerButton.mas_bottom
- make.size .width .height等等尺寸equalTo后面()的內(nèi)容
必須是一個具體的CGFloat數(shù),不能用 mas_width 等等饶米,否則會 上面的IBAction不響應(yīng) - 如果出現(xiàn)IBAction無響應(yīng)脑漫,多半是make.size/width/height的約束沒做好
- with和and都是一個宏,可以查看他咙崎,其實就是一個
return self
self.SelChildView = [[UISegmentedControl alloc] initWithItems:@[@"藍(lán)牙連接",@"WiFi連接"]];
[self.view addSubview:self.SelChildView];
// add constrains
[self.SelChildView mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(48.0f);
make.top.equalTo(mv.openDrawerButton.mas_bottom).with.offset(8.0f);
make.centerX.equalTo(mv.view。mas_centerX);
make.left.equalTo(mv.view).with.offset(8.0f);
make.right.equalTo(mv.view).with.offset(-8.0f);
make.width.equalTo(self.SelChildView.frame.size.width);//直接用equalTo(self.SelChildView.mas_width)可能會導(dǎo)致SelChildView上面的控件失效
make.height.equalTo(self.SelChildView.frame.size.height);//直接用equalTo(self.SelChildView.mas_height)可能會導(dǎo)致SelChildView上面的控件失效
}];
- 使用masonry進(jìn)行約束創(chuàng)建的尺寸吨拍,并不等于你已經(jīng)創(chuàng)建了他的frame褪猛!
-
我們來解釋下下面這張圖。
- 如果我們不寫 frame的那句羹饰,而用make.size.equalTo(CGSizeMake(5,5)); 我們看到的效果是一樣的伊滋。
-
但是!如果這樣做了队秩,是無法獲取到他的frame的值的笑旺。通過打印他的
x,y,width,height
會發(fā)現(xiàn)是0
- 使用masonry的實質(zhì)還是調(diào)用了ios7以后的autolayout,如果要升級frame馍资,必須在最后增加一句
[self.currentView.superview layoutIfNeeded];//打印他的frame發(fā)現(xiàn)已經(jīng)更新
使用和不使用Masonry下的尺寸問題
- 比如說筒主,[[UIView alloc] initWithFrame],這個frame的大小是 5x5的大小。
然后我insert一個image,大小是30x30
鸟蟹,最后顯示的時候乌妙,我們看到的圖片是30x30的 - 縮放比例,只能通過改變他的長寬來實現(xiàn)建钥,不能用
multipliedBy
來實現(xiàn)等比例縮放藤韵,不知道是什么原因!熊经! 坑掉過一次就不要忘記T笏摇欲险! - 等比例縮放的實例:
[self.openDrawerButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view).with.offset(20.0f);
make.left.equalTo(self.view).with.offset(11.0f);
// 等比例縮小 0.8
CGSize size = CGSizeMake(0.8*self.openDrawerButton.frame.size.width, 0.8*self.openDrawerButton.frame.size.height);
make.size.mas_equalTo(size);//如果添加了宏定義,這里可以不用mas_
}];
Masonry 實例匹涮,分別約束代碼創(chuàng)建和 XIB / Storyboard 創(chuàng)建的UIView
Demo 中討論了masonry配合實現(xiàn)動畫時候碰見的四種情形天试,分別是:
trytry.gif
序號 | Masonry | 純Frame | XIB | 純代碼 | 可行動畫 | 備注 |
---|---|---|---|---|---|---|
1 | ? | ?? | ? | ?? | 卷軸/平移 | 不使用masonry,通過純代碼和frame 創(chuàng)建卷軸動畫/平移動畫 |
2 | ?? | ? | ? | ?? | 卷軸/平移 | 嘗試通過masonry+純代碼方式創(chuàng)建卷軸動畫/平移,用masonry來升級 frame |
3 | ? | ?? | ?? | ? | 平移/橫向縮放 | 通過XIB創(chuàng)建DIYView + frame創(chuàng)建平移動畫,證明無法使用卷軸動畫焕盟。因為尺寸不可變(width可變秋秤,height不行) |
4 | ?? | ? | ?? | ? | 平移/橫向縮放 | 通過XIB創(chuàng)建DIYView + masonry 創(chuàng)建平移動畫和卷軸動畫(width可變,height不行),用masonry來升級 frame |
下面是四個情形的代碼
TIPS: 說明下使用masonry升級frame脚翘,形成動畫的注意點:
- mas_makeConstrains之后灼卢,在后面要加上
[self.viewX.superview layoutIfNeeded]
; 升級frame - 動畫中調(diào)用mas_updateConstrains升級他的約束,然后也要調(diào)用一次
[self.viewX.superview layoutIfNeeded]
; 升級frame - 如果約束的是XIB的DIYView来农,masonry的約束可能和XIB中的約束沖突鞋真,如果使用縮放,注意make.size的值要設(shè)置好沃于,否則可能IBAction失效
// Step 1, 通過純代碼和frame 創(chuàng)建卷軸動畫/平移動畫
self.View1 = [[UIView alloc] initWithFrame:CGRectMake(0,200, [UIScreen mainScreen].bounds.size.width, 0)];
self.View1.backgroundColor = [UIColor greenColor];
UILabel* lb = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
lb.text = @"TTY";
[self.view addSubview:self.View1];
// 動畫
[UIView animateWithDuration:10.0
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.View1.frame = CGRectMake(0, 200, [UIScreen mainScreen].bounds.size.width, 80);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.View1 addSubview:lb];
});
}
completion:^(BOOL finished) {
}];
// Step 2涩咖, 嘗試通過masonry+純代碼方式創(chuàng)建卷軸動畫,用masonry來升級 frame
self.View2 = [[UIView alloc] init];
self.View2.backgroundColor = [UIColor blackColor];
[self.view addSubview:self.View2];
[self.View2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(300);
make.left.mas_equalTo(100);
make.size.mas_equalTo(CGSizeMake(100, 100));
}];
NSLog(@"masonry 之前size = %f,%f",self.View2.frame.size.width,self.View2.frame.size.height);
[self.View2.superview layoutIfNeeded];
[UIView animateWithDuration:10.0
animations:^{
[self.View2 mas_updateConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(200);
}];
[self.View2.superview layoutIfNeeded];
}];
NSLog(@"masonry 之后size = %f,%f",self.View2.frame.size.width,self.View2.frame.size.height);
// step 3 通過XIB創(chuàng)建DIYView + frame創(chuàng)建滾動動畫,證明無法使用卷軸動畫繁莹。因為尺寸不可變(寬度可以用屏幕寬度賦值檩互,除此其他不行),只能使用滾動動畫
self.View3 = [[NSBundle mainBundle] loadNibNamed:@"BossView"
owner:self
options:nil].lastObject;
CGRect view3rect = CGRectMake([UIScreen mainScreen].bounds.size.width, 400, [UIScreen mainScreen].bounds.size.width, self.View3.frame.size.height);
self.View3.frame = view3rect;
[self.view addSubview:self.View3];
[UIView animateWithDuration:5.0
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
CGRect view3rect = CGRectMake(0, 400, [UIScreen mainScreen].bounds.size.width, self.View3.frame.size.height);
self.View3.frame = view3rect;
} completion:^(BOOL finished) {
}];
// step 4 通過XIB創(chuàng)建DIYView + masonry 創(chuàng)建滾動動畫和卷軸動畫(寬度可以改咨演,長度不能改)
self.View4 = [[NSBundle mainBundle] loadNibNamed:@"BossView"
owner:self
options:nil].lastObject;
[self.view addSubview:self.View4];
[self.View4 mas_makeConstraints:^(MASConstraintMaker *make) {
CGSize realsize = CGSizeMake(self.View4.bounds.size.width,0 );
make.size.equalTo(realsize);
make.top.equalTo(self.view.mas_top).with.offset(600);
make.centerX.equalTo(self.view.mas_centerX);
}];
[self.View4.superview layoutIfNeeded];
NSLog(@"View4 masonry 之后size = %f,%f",self.View4.frame.size.width,self.View4.frame.size.height);
[UIView animateWithDuration:10
animations:^{
[self.View4 mas_updateConstraints:^(MASConstraintMaker *make) {
CGSize realsize = CGSizeMake([UIScreen mainScreen].bounds.size.width, self.View4.bounds.size.height);
make.size.equalTo(realsize);
}];
[self.View4.superview layoutIfNeeded];
}];
---- 2018.7.12 補(bǔ)充
從渲染的幀率來看闸昨,使用約束進(jìn)行布局實質(zhì)上是會比較消耗資源的。
尤其是使用上文提到的 使用 masonry 進(jìn)行動畫
薄风。
舉一個例子饵较,我們經(jīng)常用到的 IM 類場景(如 QQ,微信)這種高開銷的 tableView
。聊天的內(nèi)容在不斷刷新遭赂,滑動后會加載新的頭像循诉,內(nèi)容等等。如果使用約束布局撇他,勢必面臨著重新渲染的情況茄猫。
這時候幀率 的卡頓會成為一個比較大的問題。
從經(jīng)驗上來總結(jié)逆粹,大開銷的場景下募疮,動畫和渲染,還是使用原始的frame
布局來做僻弹。