1、添加約束的規則
- 在創建約束之後,需要將其添加到作用的view上
- 在添加時要注意目標view需要遵循以下規則:
- 步驟
1)利用NSLayoutConstraint類創建具體的約束對象
1> 一個NSLayoutConstraint對象就代表一個約束
2> 創建約束對象的常用方法
+(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
參數說明
pview1 :要約束的控件
pattr1 :約束的類型(做怎樣的約束)
prelation :與參照控件之間的關係
pview2 :參照的控件
pattr2 :約束的類型(做怎樣的約束)
pmultiplier :乘數
pc :常量
2)添加約束對象到相應的view上
- (void)addConstraint:(NSLayoutConstraint *)constraint;
- (void)addConstraints:(NSArray *)constraints;
- 注意點
1)要先禁止autoresizing功能,設置view的下面屬性爲NO
view.translatesAutoresizingMaskIntoConstraints = NO;
如果不設置爲NO,系統會自動將AutoresizingMask轉爲Autolayout的約束,從而造成約束衝突,控制檯打印內容如下:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSAutoresizingMaskLayoutConstraint:0x7ff339620540 h=--& v=--& V:[UIView:0x7ff339714510(0)]>",
"<NSLayoutConstraint:0x7ff339714990 V:[UIView:0x7ff339714510(40)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7ff339714990 V:[UIView:0x7ff339714510(40)]>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2)添加約束之前,一定要保證相關控件都已經在各自的父控件上,也就是將子控件添加到父控件上
3)不用再給view設置frame
- 代碼:
UIView *blueView = [[UIView alloc] init]; blueView.backgroundColor = [UIColor blueColor]; // 不要將AutoresizingMask轉爲Autolayout的約束 blueView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:blueView]; UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; // 不要將AutoresizingMask轉爲Autolayout的約束 redView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:redView];// 添加寬度約束:100 /************************** 藍色 **************************/ // 添加高度約束:40 NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:40]; [blueView addConstraint:heightConstraint]; // 添加左邊約束:blueView的左邊距離父控件左邊有20的間距 NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20]; [self.view addConstraint:leftConstraint]; // 添加右邊約束:blueView的右邊距離父控件右邊有20的間距 NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20]; [self.view addConstraint:rightConstraint]; // 添加頂部約束:blueView的頂部距離父控件頂部有20的間距 NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:20]; [self.view addConstraint:topConstraint]; /************************** 紅色 **************************/ // 添加高度約束:藍色等高 NSLayoutConstraint *heightConstraint2 = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0]; [self.view addConstraint:heightConstraint2]; // 添加左邊約束:redView的左邊 == 父控件的中心x NSLayoutConstraint *leftConstraint2 = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]; [self.view addConstraint:leftConstraint2]; // 添加頂部約束:redView的頂部距離blueView的底部有20的間距 NSLayoutConstraint *topConstraint2 = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20]; [self.view addConstraint:topConstraint2]; // 添加右邊約束:redView的右邊 == blueView的右邊 NSLayoutConstraint *rightConstraint2 = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]; [self.view addConstraint:rightConstraint2];
效果圖如下:
3、VFL語言
- 什麼是VFL語言
VFL全稱是Visual Format Language,翻譯過來是“可視化格式語言”
VFL是蘋果公司爲了簡化Autolayout的編碼而推出的抽象語言
- VFL示例:
1)H:[cancelButton(72)]-12-[acceptButton(50)]
canelButton寬72,acceptButton寬50,它們之間間距12
2)H:[wideView(>=60@700)]
wideView寬度大於等於60point,該約束條件優先級爲700(優先級最大值爲1000,優先級越高的約束越先被滿足)
3)V:[redBox][yellowBox(==redBox)]
豎直方向上,先有一個redBox,其下方緊接一個高度等於redBox高度的yellowBox
4)H:|-10-[Find]-[FindNext]-[FindField(>=20)]
水平方向上,Find距離父view左邊緣默認間隔寬度,之後是FindNext距離Find間隔默認寬度;再之後是寬度不小於20的FindField,它和FindNext以及父view右邊緣的間距都是默認寬度。(豎線“|” 表示superview的邊緣)
- VFL的使用
1)使用VFL來創建約束數組方法
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
2)創建一個字典(內部包含VFL語句中用到的控件)的快捷宏定義
NSDictionaryOfVariableBindings(...)
代碼:NSDictionaryOfVariableBindings(v1, v2, v3) 和 [NSDictionary dictionaryWithObjectsAndKeys:v1, @"v1", v2, @"v2", v3, @"v3", nil] 是等價的
- 代碼:
UIView *blueView = [[UIView alloc] init]; blueView.backgroundColor = [UIColor blueColor]; // 不要將AutoresizingMask轉爲Autolayout的約束 blueView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:blueView]; UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; // 不要將AutoresizingMask轉爲Autolayout的約束 redView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:redView]; // 間距 NSNumber *margin = @20; // 添加水平方向的約束 NSString *vfl = @"H:|-margin-[blueView]-margin-[redView(==blueView)]-margin-|"; NSDictionary *views = NSDictionaryOfVariableBindings(blueView, redView); NSDictionary *mertrics = NSDictionaryOfVariableBindings(margin); NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:vfl options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:mertrics views:views]; [self.view addConstraints:constraints]; // 添加豎直方向的間距 NSNumber *height = @40; NSString *vfl2 = @"V:[blueView(height)]-margin-|"; NSDictionary *mertrics2 = NSDictionaryOfVariableBindings(margin, height); NSArray *constraints2 = [NSLayoutConstraint constraintsWithVisualFormat:vfl2 options:kNilOptions metrics:mertrics2 views:views]; [self.view addConstraints:constraints2];
效果圖如下:
VFL存在一定的缺陷,它只能滿足大部分的約束,不能滿足存在倍數關係的約束!