Autolayout:
最重要的兩個概念
:
-
約束
:對控件位置和大小的限定條件 -
參照
:對控件設置的約束是相對于哪一個視圖而言的
自動布局的核心計算公式:
obj1.property1 =(obj2.property2 * multiplier)+ constant value
解釋:obj1的property1屬性等于obj2的property2屬性乘以multiplier(系數(shù))再加constant(常量);
約束的優(yōu)先級:
約束的priority
屬性表示約束的優(yōu)先級苟翻,取值區(qū)間為[0,1000],默認為1000。priority
值越大遍蟋,表示優(yōu)先級越高,會優(yōu)先執(zhí)行。優(yōu)先級低的約束只有在優(yōu)先級較高的約束失效后才會執(zhí)行。
警告和錯誤:
在使用storyboard和xib設置約束時裁僧,約束有可能會變成黃色或者紅色。當發(fā)生這樣的情況時慕购,就說明設置的約束有問題聊疲。
- 如果約束是黃色的,這只是一個警告沪悲,代表控件的frame和設置的約束不相符获洲,更新frame或者更新約束就可以解決。
- 如果約束是紅色的殿如,這就代表錯誤贡珊,約束設置不完全或者某兩個約束有沖突最爬,只有約束設置完整并且沒有沖突,紅色錯誤提示才會消失飞崖。
添加約束的3條規(guī)則:
- 對于兩個同層級View之間的約束關系烂叔,應該添加到它們的父View之上。
-
對于兩個不同層級View之間的約束關系固歪,應該添加到它們最近的共同父View上蒜鸡。
- 對于有層次關系的兩個view之間的約束關系,添加到層次較高的父view上
代碼實現(xiàn)Autolayout:
代碼實現(xiàn)Autolayout需要注意:
- 必須先禁止autoresizing功能牢裳,設置View的下面屬性為
NO
:
view.translatesAutoresizingMaskIntoConstraints = NO;
- 添加約束之前逢防,一定要保證相關控件都已經添加到各自的父控件上了
- 不用再給View設置frame
利用NSLayoutConstraint
類創(chuàng)建具體的約束對象
添加約束到相應的View上:
- (void)addConstraint:(NSLayoutConstraint *)constraint;
- (void)addConstraints:(NSArray *)constraints;
NSLayoutConstraint
:
一個NSLayoutConstraint
對象就代表一個約束,可以通過修改NSLayoutConstraint
對象的屬性來修改約束蒲讯。
創(chuàng)建約束對象常用的方法:
/**
* 添加一個約束忘朝,其實就是根據(jù)公式來計算約束
* obj1.property1 =(obj2.property2 * multiplier)+ constant value
* @param view1 需要添加約束的View
* @param attr1 需要添加的約束(左邊、右邊判帮、長寬還是局嘁。。晦墙。)
* @param relation 約束關系(大于悦昵、等于還是小于)
* @param view2 參照View(約束是相對于哪個View而言)
* @param attr2 參照View的哪一個參數(shù)(左邊、右邊晌畅、長寬還是但指。。抗楔。)
* @param multiplier 系數(shù)
* @param c 常量值
*
* @return 返回一個創(chuàng)建好的約束
*/
+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
示例:
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
//關閉Autoresizing
blueView.translatesAutoresizingMaskIntoConstraints = NO;
//創(chuàng)建左邊約束
NSLayoutConstraint *leftLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20];
[self.view addConstraint:leftLc];
//創(chuàng)建右邊約束
NSLayoutConstraint *rightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20];
[self.view addConstraint:rightLc];
//創(chuàng)建底部約束
NSLayoutConstraint *bottomLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-20];
[self.view addConstraint:bottomLc];
//創(chuàng)建高度約束
NSLayoutConstraint *heightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:50];
[blueView addConstraint: heightLc];
效果圖:
使用VFL語句添加約束:
使用VFL來創(chuàng)建約束數(shù)組:
/**
* 使用VFL語句來創(chuàng)建約束數(shù)組
*
* @param format VFL語句
* @param opts 約束類型
* @param metrics VFL語句中用到的具體數(shù)值
* @param views VFL語句中用到的控件
*
* @return 返回創(chuàng)建好的約束數(shù)組
*/
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;
VFL語句示例:
H:[cancelButton(72)]-12-[acceptButton(50)]
canelButton寬72棋凳,acceptButton寬50,它們之間間距12
H:[wideView(>=60@700)]
wideView寬度大于等于60point连躏,該約束條件優(yōu)先級為700(優(yōu)先級最大值為1000剩岳,優(yōu)先級越高的約束越先被滿足)
V:[redBox][yellowBox(==redBox)]
豎直方向上,先有一個redBox入热,其下方緊接一個高度等于redBox高度的yellowBox
H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
水平方向上卢肃,F(xiàn)ind距離父view左邊緣默認間隔寬度,之后是FindNext距離Find間隔默認寬度才顿;再之后是寬度不小于20的FindField莫湘,它和FindNext以及父view右邊緣的間距都是默認寬度。(豎線“|” 表示superview的邊緣)
VFL代碼示例:
// 創(chuàng)建藍色View
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
blueView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:blueView];
// 創(chuàng)建紅色View
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
redView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:redView];
// VFL創(chuàng)建約束
// 水平方向
NSString *VFL_H = @"H:|-space-[blueView]-space-[redView(==blueView)]-space-|";
NSDictionary *metrics = @{
@"space" : @30,
};
// NSDictionary *views = @{
// @"blueView" : blueView,
// @"redView" : redView
// };
NSDictionary *views = NSDictionaryOfVariableBindings(blueView,redView);
NSArray *arrayH = [NSLayoutConstraint constraintsWithVisualFormat:VFL_H options:NSLayoutFormatAlignAllTop metrics:metrics views:views];
[self.view addConstraints:arrayH];
// 垂直方向
NSString *VFL_V = @"V:[blueView(50)]-space-|";
NSArray *arrayV = [NSLayoutConstraint constraintsWithVisualFormat:VFL_V options:kNilOptions metrics:metrics views:views];
[self.view addConstraints:arrayV];
// 添加紅色View的約束
// 添加高度約束
NSLayoutConstraint *redV_height = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0];
[self.view addConstraint:redV_height];
效果圖:
Masonry的使用:
Masonry是目前最流行的Autolayout第三方框架郑气,讓你可以用簡單的代碼來編寫Autolayout幅垮,省去了蘋果官方繁復的Autolayout代碼,大大提升了開發(fā)效率尾组。
mas_equalTo
和equalTo
:
默認情況下mas_equalTo
有自動包裝功能忙芒,比如自動將20
包裝為@20
示弓。equalTo
沒有自動包裝功能。
如果添加了下面的宏呵萨,那么mas_equalTo
和equalTo
就沒有區(qū)別:
#define MAS_SHORTHAND_GLOBALS
// 注意:這個宏一定要添加到#import "Masonry.h"前面
mas_width
和width
:
默認情況下
width
是make
對象的一個屬性奏属,用來添加寬度約束用的,表示對寬度進行約束潮峦。mas_width
是一個屬性值囱皿,用來當做equalTo
的參數(shù),表示某個控件的寬度屬性忱嘹。
如果添加了下面的宏嘱腥,mas_width
也可以寫成width
:
#define MAS_SHORTHAND
mas_height
、mas_centerX
以此類推拘悦。
下面用Masonry框架實現(xiàn)一下上面VFL語句的示例齿兔,對比一下就會發(fā)現(xiàn)有了Masonry框架以后自動布局變得多么容易:
//創(chuàng)建藍色控件
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
//創(chuàng)建紅色控件
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
// 添加blueView的約束
[blueView makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(redView.width).offset(0);
make.height.equalTo(redView.height).offset(0);
make.height.equalTo(100);
make.left.equalTo(blueView.superview.left).offset(20);
make.bottom.equalTo(blueView.superview.bottom).offset(-20);
make.right.equalTo(redView.left).offset(-20);
}];
// 添加redView的約束
[redView makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(redView.superview.bottom).offset(-20);
make.right.equalTo(redView.superview.right).offset(-20);
}];
Masonry框架提供了很多示例程序,感興趣的可以打開上面GitHub的鏈接下載下來仔細研究础米,這里就不多寫了分苇。
GitHub鏈接為:https://github.com/SnapKit/Masonry
約束動畫:
在執(zhí)行動畫時記得調用以下方法:
//在修改了約束之后,只要執(zhí)行下面代碼屁桑,約束就能做出動畫效果
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
}];
使用Autolayout實現(xiàn)UILabel內容包裹:
- 1医寿、設置UILabel的位置約束
- 2、設置
label.numberOfLines = 0;
,使label能夠自動換行來計算高度 - 3掏颊、代碼創(chuàng)建約束時,應設置label的最大寬度
preferredMaxLayoutWidth
艾帐。