現(xiàn)在iPhone手機屏幕越來越多, 屏幕適配也越來越重要. Masonry就是為屏幕適配而生的三方框架.
Masonry基礎(chǔ)API
mas_makeConstraints() 添加約束
mas_remakeConstraints() 移除之前的約束,重新添加新的約束
mas_updateConstraints() 更新約束,寫哪條更新哪條,其他約束不變
equalTo() 參數(shù)是對象類型,一般是視圖對象或者mas_width這樣的坐標系對象
mas_equalTo() 和上面功能相同,參數(shù)可以傳遞基礎(chǔ)數(shù)據(jù)類型對象,可以理解為比上面的API更強大
width() 用來表示寬度,例如代表view的寬度
mas_width() 用來獲取寬度的值。和上面的區(qū)別在于,一個代表某個坐標系對象,一個用來獲取坐標系對象的值
更新約束和布局
- (void)updateConstraintsIfNeeded 調(diào)用此方法,如果有標記為需要重新布局的約束,則立即進行重新布局,內(nèi)部會調(diào)用updateConstraints方法
- (void)updateConstraints 重寫此方法,內(nèi)部實現(xiàn)自定義布局過程
- (BOOL)needsUpdateConstraints 當前是否需要重新布局,內(nèi)部會判斷當前有沒有被標記的約束
- (void)setNeedsUpdateConstraints 標記需要進行重新布局
Masonry示例代碼
Masonry本質(zhì)上就是對系統(tǒng)AutoLayout進行的封裝,包括里面很多的API,都是對系統(tǒng)API進行了一次二次包裝。
typedef NS_OPTIONS(NSInteger, MASAttribute) {
MASAttributeLeft = 1 << NSLayoutAttributeLeft,
MASAttributeRight = 1 << NSLayoutAttributeRight,
MASAttributeTop = 1 << NSLayoutAttributeTop,
MASAttributeBottom = 1 << NSLayoutAttributeBottom,
MASAttributeLeading = 1 << NSLayoutAttributeLeading,
MASAttributeTrailing = 1 << NSLayoutAttributeTrailing,
MASAttributeWidth = 1 << NSLayoutAttributeWidth,
MASAttributeHeight = 1 << NSLayoutAttributeHeight,
MASAttributeCenterX = 1 << NSLayoutAttributeCenterX,
MASAttributeCenterY = 1 << NSLayoutAttributeCenterY,
MASAttributeBaseline = 1 << NSLayoutAttributeBaseline,
};
常用方法
設(shè)置內(nèi)邊距
/**
設(shè)置yellow視圖和self.view等大,并且有10的內(nèi)邊距。
注意根據(jù)UIView的坐標系,下面right和bottom進行了取反。所以不能寫成下面這樣,否則right、bottom這兩個方向會出現(xiàn)問題。
make.edges.equalTo(self.view).with.offset(10);
除了下面例子中的offset()方法,還有針對不同坐標系的centerOffset()、sizeOffset()、valueOffset()之類的方法。
*/
[self.yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).with.offset(10);
make.top.equalTo(self.view).with.offset(10);
make.right.equalTo(self.view).with.offset(-10);
make.bottom.equalTo(self.view).with.offset(-10);
}];
通過insets簡化設(shè)置內(nèi)邊距的方式
// 下面的方法和上面例子等價,區(qū)別在于使用insets()方法。
[self.blueView mas_makeConstraints:^(MASConstraintMaker *make) {
// 下、右不需要寫負號,insets方法中已經(jīng)為我們做了取反的操作了。
make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
}];
更新約束
// 設(shè)置greenView的center和size,這樣就可以達到簡單進行約束的目的
[self.greenView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
// 這里通過mas_equalTo給size設(shè)置了基礎(chǔ)數(shù)據(jù)類型的參數(shù),參數(shù)為CGSize的結(jié)構(gòu)體
make.size.mas_equalTo(CGSizeMake(300, 300));
}];
// 為了更清楚的看出約束變化的效果,在顯示兩秒后更新約束。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 指定更新size,其他約束不變。
[self.greenView mas_updateConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(100, 100));
}];
});
大于等于和小于等于某個值的約束
[self.textLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
// 設(shè)置寬度小于等于200
make.width.lessThanOrEqualTo(@200);
// 設(shè)置高度大于等于10
make.height.greaterThanOrEqualTo(@(10));
}];
self.textLabel.text = @"這是測試的字符串。能看到1、2、3個步驟,第一步當然是上傳照片了,要上傳正面近照哦。上傳后,網(wǎng)站會自動識別你的面部,如果覺得識別的不準,你還可以手動修改一下。左邊可以看到16項修改參數(shù),最上面是整體修改,你也可以根據(jù)自己的意愿單獨修改某項,將鼠標放到選項上面,右邊的預覽圖會顯示相應的位置。";
textLabel只需要設(shè)置一個屬性即可
self.textLabel.numberOfLines = 0;
使用基礎(chǔ)數(shù)據(jù)類型當做參數(shù)
/**
如果想使用基礎(chǔ)數(shù)據(jù)類型當做參數(shù),Masonry為我們提供了"mas_xx"格式的宏定義。
這些宏定義會將傳入的基礎(chǔ)數(shù)據(jù)類型轉(zhuǎn)換為NSNumber類型,這個過程叫做封箱(Auto Boxing)。
"mas_xx"開頭的宏定義,內(nèi)部都是通過MASBoxValue()函數(shù)實現(xiàn)的。
這樣的宏定義主要有四個,分別是mas_equalTo()、mas_offset()和大于等于、小于等于四個。
*/
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.width.mas_equalTo(100);
make.height.mas_equalTo(100);
}];
設(shè)置約束優(yōu)先級
/**
Masonry為我們提供了三個默認的方法,priorityLow()、priorityMedium()、priorityHigh(),這三個方法內(nèi)部對應著不同的默認優(yōu)先級。
除了這三個方法,我們也可以自己設(shè)置優(yōu)先級的值,可以通過priority()方法來設(shè)置。
*/
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.width.equalTo(self.view).priorityLow();
make.width.mas_equalTo(20).priorityHigh();
make.height.equalTo(self.view).priority(200);
make.height.mas_equalTo(100).priority(1000);
}];
Masonry也幫我們定義好了一些默認的優(yōu)先級常量,分別對應著不同的數(shù)值,優(yōu)先級最大數(shù)值是1000。
static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired;
static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh;
static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500;
static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow;
static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel;
設(shè)置約束比例
// 設(shè)置當前約束值乘以多少,例如這個例子是redView的寬度是self.view寬度的0.2倍。
[self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.height.mas_equalTo(30);
make.width.equalTo(self.view).multipliedBy(0.2);
}];
小練習
子視圖等高/等寬練習
/**
下面的例子是通過給equalTo()方法傳入一個數(shù)組,設(shè)置數(shù)組中子視圖及當前make對應的視圖之間等高。
需要注意的是,下面block中設(shè)置邊距的時候,應該用insets來設(shè)置,而不是用offset。
因為用offset設(shè)置right和bottom的邊距時,這兩個值應該是負數(shù),所以如果通過offset來統(tǒng)一設(shè)置值會有問題。
*/
CGFloat padding = 10;
UIView *redView = [[UIView alloc]init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
UIView *blueView = [[UIView alloc]init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
UIView *yellowView = [[UIView alloc]init];
yellowView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:yellowView];
/********** 等高 ***********/
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.equalTo(self.view).insets(UIEdgeInsetsMake(padding, padding, 0, padding));
make.bottom.equalTo(blueView.mas_top).offset(-padding);
}];
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view).insets(UIEdgeInsetsMake(0, padding, 0, padding));
make.bottom.equalTo(yellowView.mas_top).offset(-padding);
}];
/**
下面設(shè)置make.height的數(shù)組是關(guān)鍵,通過這個數(shù)組可以設(shè)置這三個視圖高度相等。其他例如寬度之類的,也是類似的方式。
*/
[yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.equalTo(self.view).insets(UIEdgeInsetsMake(0, padding, padding, padding));
make.height.equalTo(@[blueView, redView]);
}];
/********** 等寬 ***********/
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.bottom.equalTo(self.view).insets(UIEdgeInsetsMake(padding, padding, padding, 0));
make.right.equalTo(blueView.mas_left).offset(-padding);
}];
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self.view).insets(UIEdgeInsetsMake(padding, 0, padding, 0));
make.right.equalTo(yellowView.mas_left).offset(-padding);
}];
[yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.right.equalTo(self.view).insets(UIEdgeInsetsMake(padding, 0, padding, padding));
make.width.equalTo(@[redView, blueView]);
}];

等高

等寬
子視圖垂直居中練習
CGFloat padding = 10;
UIView *redView = [[UIView alloc]init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
UIView *blueView = [[UIView alloc]init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.view);
make.left.equalTo(self.view).mas_offset(padding);
make.right.equalTo(blueView.mas_left).mas_offset(-padding);
//make.width.equalTo(blueView);
make.height.mas_equalTo(150);
}];
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.view);
make.right.equalTo(self.view).mas_offset(-padding);
make.width.equalTo(redView);
make.height.mas_equalTo(150);
}];

子視圖垂直居中練習