iOS开发之 Autolayout 详解
iOS開發之 Autolayout 詳解
1. 概述
2. 代碼實現 Autolayout
2.1 步驟:
添加約束到相應的 View 上。
- (void)addConstraint:(NSLayoutConstraint *)constraint; - (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints;obj1.property1 =(obj2.property2 * multiplier)+ constant value
NSLayoutConstraint
/** view1 :要約束的控件 attr1 :約束的類型(做怎樣的約束) relation :與參照控件之間的關系 view2 :參照的控件 attr2 :約束的類型(做怎樣的約束) multiplier :乘數 c :常量 */ + (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;2.2 實例
添加一個左間距100 上間距200,寬150 高64 的紅視圖:
- (void)testAutolayout1 {UIView *redV = [[UIView alloc] init];redV.backgroundColor = [UIColor redColor];redV.translatesAutoresizingMaskIntoConstraints = NO;[self.view addSubview:redV];/**view1 :要約束的控件attr1 :約束的類型(做怎樣的約束)relation :與參照控件之間的關系view2 :參照的控件attr2 :約束的類型(做怎樣的約束)multiplier :乘數c :常量*//// 左間距100:NSLayoutConstraint *consLeft = [NSLayoutConstraint constraintWithItem:redV attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:100];[self.view addConstraint:consLeft];/// 上間距200:NSLayoutConstraint *consTop = [NSLayoutConstraint constraintWithItem:redV attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:200];[self.view addConstraint:consTop];/// 寬150:NSLayoutConstraint *consWidth = [NSLayoutConstraint constraintWithItem:redV attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:150];[redV addConstraint:consWidth];/// 高64:NSLayoutConstraint *consHeight = [NSLayoutConstraint constraintWithItem:redV attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:64];[redV addConstraint:consHeight]; }在上視圖基礎上添加一個與紅視圖右間距相同,高度相同,頂部距離紅色視圖間距20,寬度為紅色視圖一半的藍色View
UIView *blueV = [[UIView alloc] init];blueV.backgroundColor = [UIColor blueColor];blueV.translatesAutoresizingMaskIntoConstraints = NO;[self.view addSubview:blueV];/// 和 redV 右間距為0NSLayoutConstraint *b_consRight = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0];[self.view addConstraint:b_consRight];/// 和 redV 等高NSLayoutConstraint *b_consHeight = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0];[self.view addConstraint:b_consHeight];/// 寬度是 redV 的一半NSLayoutConstraint *b_consWidth = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0.0];[self.view addConstraint:b_consWidth];/// 頂部距離 redV 20NSLayoutConstraint *b_consTop = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20.0];[self.view addConstraint:b_consTop];最終效果:
2.3 添加約束的規則
在創建約束之后,需要將其添加到作用的view上。
在添加時要注意目標view需要遵循以下規則:
(1)對于兩個同層級view之間的約束關系,添加到它們的父view上
(2)對于兩個不同層級view之間的約束關系,添加到他們最近的共同父view上
(3)對于有層次關系的兩個view之間的約束關系,添加到層次較高的父view上
3. VFL
VFL全稱是Visual Format Language,翻譯過來是“可視化格式語言”,是蘋果公司為了簡化Autolayout的編碼而推出的抽象語言。
/*format :VFL語句opts :約束類型metrics :VFL語句中用到的具體數值views :VFL語句中用到的控件*/ + (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *,id> *)views;@{@"redV" : redV} 等價于 NSDictionaryOfVariableBindings(redV)
NSDictionary *views =NSDictionaryOfVariableBindings(blueView, redView);NSArray *conts2 =[NSLayoutConstraint constraintsWithVisualFormat:@"V:[blueView(==blueHeight)]-margin-|" options:0 metrics:@{@"blueHeight" : @40, @"margin" : @20} views:views];約束格式說明:
水平方向 H:
垂直方向 V:
Views [view]
SuperView |
關系 >=,==,<=
空間,間隙 -
優先級 @value
3.1 VFL 部分語法:
H:|-100-[redV(200)]-|
水平方向距離左邊距100,寬度200
V:|-200-[redV(64)]-|
垂直方向距離頂部200,高度64
H:[redV(72)]-12-[blueV(50)]
水平方向redV 寬度72,blueV 寬度50,他們之間間距12
H:[redV(>=60@700)]
水平方向redV寬度大于等于60,優先級為700 (優先級最大1000)
V:[redBox]-[yellowBox(==redBox)]
豎直方向上,先有一個redBox,其下方緊接一個高度等于redBox高度的yellowBox
H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
水平方向上,Find距離父view左邊緣默認間隔寬度,之后是FindNext距離Find間隔默認寬度;再之后是寬度不小于20的FindField,它和FindNext以及父view右邊緣的間距都是默認寬度。(豎線“|” 表示superview的邊緣)
3.2 VFL的語法
- 標準間隔:[button]-[textField]
- 寬約束:[button(>=50)]
- 與父視圖的關系:|-50-[purpleBox]-50-|
- 垂直布局:V:[topField]-10-[bottomField]
- Flush Views:[maroonView][buleView]
- 權重:[button(100@20)]
- 等寬:[button(==button2)]
- Multiple Predicates:[flexibleButton(>=70,<=100)]
注意事項
創建這種字符串時需要注意一下幾點:
* H:和V:每次都使用一個。
* 視圖變量名出現在方括號中,例如[view]。
* 字符串中順序是按照從頂到底,從左到右
* 視圖間隔以數字常量出現,例如-10-。
* |表示父視圖
3.3 使用Auto Layout時需要注意的點
- 注意禁用Autoresizing Masks。對于每個需要使用Auto Layout的視圖需要調用setTranslatesAutoresizingMaskIntoConstraints:NO
- VFL語句里不能包含空格和>,<這樣的約束
- 布局原理是由外向里布局,最先屏幕尺寸,再一層一層往里決定各個元素大小。
- 刪除視圖時直接使用removeConstraint和removeConstraints時需要注意這樣刪除是沒法刪除視圖不支持的約束導致view中還包含著那個約束(使用第三方庫時需要特別注意下)。解決這個的辦法就是添加約束時用一個局部變量保存下,刪除時進行比較刪掉和先前那個,還有個辦法就是設置標記,constraint.identifier = @“What you want to call”。
3.4 布局約束規則
表達布局約束的規則可以使用一些簡單的數學術語,如下表
| 屬性 | 視圖位置 | NSLayoutAttributeLeft, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom |
| 屬性 | 視圖前面后面 | NSLayoutAttributeLeading, NSLayoutAttributeTrailing |
| 屬性 | 視圖的寬度和高度 | NSLayoutAttributeWidth, NSLayoutAttributeHeight |
| 屬性 | 視圖中心 | NSLayoutAttributeCenterX, NSLayoutAttributeCenterY |
| 屬性 | 視圖的基線,在視圖底部上方放置文字的地方 | NSLayoutAttributeBaseline |
| 屬性 | 占位符,在與另一個約束的關系中沒有用到某個屬性時可以使用占位符 | NSLayoutAttributeNotAnAttribute |
| 關系 | 允許將屬性通過等式和不等式相互關聯 | NSLayoutRelationLessThanOrEqual, NSLayoutRelationEqual, NSLayoutRelationGreaterThanOrEqual |
| 數學運算 | 每個約束的乘數和相加性常數 | CGFloat值 |
3.5 View的改變會調用哪些方法
- 改變frame.origin不會掉用layoutSubviews
- 改變frame.size會使 superVIew的layoutSubviews調用和自己view的layoutSubviews方法
- 改變bounds.origin和bounds.size都會調用superView和自己view的layoutSubviews方法
3.6 VFL 實例:
- (void)testVFL {UIView *redV = [[UIView alloc] init];redV.backgroundColor = [UIColor redColor];redV.translatesAutoresizingMaskIntoConstraints = NO;[self.view addSubview:redV];UIView *blueV = [[UIView alloc] init];blueV.backgroundColor = [UIColor blueColor];blueV.translatesAutoresizingMaskIntoConstraints = NO;[self.view addSubview:blueV];/*format :VFL語句opts :約束類型metrics :VFL語句中用到的具體數值views :VFL語句中用到的控件*///水平方向 redV 左右間距為20NSArray *cons1 = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[redV]-20-|" options:0 metrics:nil views:@{@"redV":redV}];[self.view addConstraints:cons1];//垂直方法redV距離頂部 100, redV 高度為64, blueV頂部距離redV 100 像素, blueV的高度等于redVNSArray *cons2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-margin-[redV(64)]-margin-[blueV(==redV)]" options:NSLayoutFormatAlignAllRight metrics:@{@"margin" : @100} views:NSDictionaryOfVariableBindings(redV,blueV)];[self.view addConstraints:cons2];NSLayoutConstraint *cons = [NSLayoutConstraint constraintWithItem:blueV attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:redV attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0.0];[self.view addConstraint:cons]; }運行結果:
文中演示Demo 均已開源在 GitHub上,這是鏈接: XWAutolayoutDemo In Github
總結
以上是生活随笔為你收集整理的iOS开发之 Autolayout 详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习方法:受限玻尔兹曼机RBM(三)
- 下一篇: linux部署jenkins,tomca