自動佈局 1 什麼是自動佈局? UI 根據不同尺寸的屏幕動態的佈局控制項大小. 2 作用 適配所有機型 3 佈局中常用的參數 autoResizing就是一個相對於父控制項的佈局解決方法;由於它只能相對父控制項佈局;因此不能約束子控制項之間關係. 所以出現了aotolayout,既可以設置父子控制項之間的關係 ...
自動佈局
1 什麼是自動佈局?
UI 根據不同尺寸的屏幕動態的佈局控制項大小.
2 作用
適配所有機型
3 佈局中常用的參數
- autoResizing就是一個相對於父控制項的佈局解決方法;由於它只能相對父控制項佈局;因此不能約束子控制項之間關係. 所以出現了aotolayout,既可以設置父子控制項之間的關係也可以設置同級控制項之間的關係
- 註: 在用autoResizing的時候需要關閉autoLayout和sizeclass,因為他們之間是互相衝突的.
- Autolayout的作用非常明確:幫我們確定在不同設備、不同(父view)環境下,同一個可視單元所應具有合適的位置和尺寸,因此,當一個 UIView上所施加的約束能夠唯一確定它的frame(x, y, width, height)的時候我們的自動佈局的使用才是正確的
- sizeClass: 對屏幕尺寸進行了抽象.
4 Autolayout的兩條核心概念:
>1 參照:通過參照其他控制項或父控制項來設置當前控制項地位置和大小
>2 約束Constraints(規則):通過添加約束限制控制項地位置和大小
5 代碼實現Autolayout的步驟:
5.1 利用NSLayoutConstraint類創建具體的約束對象
5.2 添加約束對象到相應的view上
- (void)addConstraint:(NSLayoutConstraint *)constraint;
- (void)addConstraints:(NSArray *)constraints;
5.3 代碼實現Autolayout的註意點:
> 要先禁止autoresizing功能,設置view的下麵屬性為NO
view.translatesAutoresizingMaskIntoConstraints = NO;
> 添加約束之前,一定要保證相關控制項都已經在各自的父控制項上
> 不用再給view設置frame
> 自動佈局有個核心公式:
obj1.property1 =(obj2.property2 * multiplier)+ constant value
6 自動佈局的三種方法及優缺點
- 純代碼
優點: 純代碼實現UI具有最好的代碼重用性,也利用版本管理、代碼追蹤和代碼的合併,大型項目大規模的使用。
缺點:純代碼實現存在的問題是開發周期長,代碼的維護複雜以及自動佈局AutoLayout困難
- storyboard
優點: StoryBoard實現的優點主要凸顯在開發周期短,代碼量少,可以明確看到每個ViewController的佈局樣式和各個控制器之間的跳轉關係。
缺點:當然它的弊端也顯而易見,不合適多人協作開發,ViewController的重用和自定義view的實現.
- XIB
優點: Xib的優勢在於開發周期快而且版本的維護和純代碼差異性不大,易於維護。
缺點:它的劣勢往往體現在Xib的設置往往不是最終的設置,終究會被純代碼所替代。Xib的使用註意點:儘量將xib的工作和代碼的工作隔離開來:能夠使用xib完成的內容就統一使用xib來做.
7 自動佈局的實現
自動佈局經過的三個時期
MagicNumber -> autoresizingMask -> autolayout
> 在iphone1-iphone3gs時代 window的size固定為(320,480) 我們只需要簡單計算一下相對位置就好了
> 在iphone4-iphone4s時代蘋果推出了retina屏 但是window的size不變
>在iphone5-iphone5s時代 window的size變了(320,568) 這時autoresizingMask
> autoLayout自動佈局是iOS6.0之後推出的,在6.0之前多使用autoresizingMasks屬性,這個枚舉類型的屬性都是flexible(伸縮),在有了autoLayout之後這個就很少用了,可以不做瞭解。
StoryBoard和Xib設置約束在這裡也不做具體的介紹,主要介紹三種手寫代碼設置約束的方法。
1、使用系統的NSLayoutConstraint實現
obj1.property1 =(obj2.property2 * multiplier)+ constant value
multiplier和constant 就是向量繫數和偏移量
1) 一個一個設置約束
-(void)addConstraint:(NSLayoutConstraint *)constraint;
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_testView1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:30]];
2) 一組一組設置約束
- (void)addConstraints:(NSArray *)constraints;
[self.view addConstraints:@[
//上
[NSLayoutConstraint constraintWithItem:_testView1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:30],
//左
[NSLayoutConstraint constraintWithItem:_testView1 attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:10],
//下
[NSLayoutConstraint constraintWithItem:_testView1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-170],
//寬
[NSLayoutConstraint constraintWithItem:_testView1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.45 constant:0]]];
2) Visual Format Language,翻譯過來是“可視化格式語言” 是蘋果公司為了簡化Autolayout的編碼而推出的抽象語言 相當於打出象形文字似得,而且要全在字元串里寫,遇到錯誤比較難調,但是相對來說代碼精簡了不少.
VFL的詳細語法 可以在官方文檔中 搜“Visual Format” 就能搜到
上面的方法中傳到的兩個參數metrics 和 views 是兩個字典。
第一個字典metrics是用來告訴系統裡面的每一個值對應哪個字母
第二個字典views是 用來告訴裡面的每一個控制項對應字元串里的什麼
如果整個VFL語言里的所有控制項你都是用原名寫在裡面的,那可以用巨集代替
註釋:
|: 表示父視圖
-:表示距離
V: :表示垂直
H: :表示水平
>= :表示視圖間距、寬度和高度必須大於或等於某個值
<= :表示視圖間距、寬度和高度必須小宇或等於某個值
== :表示視圖間距、寬度或者高度必須等於某個值
@ :>=、<=、== 限制 最大為 1000
1.|-[view]-|: 視圖處在父視圖的左右邊緣內
2.|-[view] : 視圖處在父視圖的左邊緣
3.|[view] : 視圖和父視圖左邊對齊
4.-[view]- : 設置視圖的寬度高度
5.|-30.0-[view]-30.0-|: 表示離父視圖 左右間距 30
6.[view(200.0)] : 表示視圖寬度為 200.0
7.|-[view(view1)]-[view1]-| :表示視圖寬度一樣,並且在父視圖左右邊緣內
8. V:|-[view(50.0)] : 視圖高度為 50
9: V:|-(==padding)-[imageView]->=0-[button]-(==padding)-| : 表示離父視圖的距離
這兩個視圖間距必須大於或等於0並且距離底部父視圖為padding。
10: [wideView(>=60@700)] :視圖的寬度為至少為60 不能超過 700
11: 如果沒有聲明方向預設為 水平 H:
- (void)setConstraintsByVFL {
NSDictionary *views = NSDictionaryOfVariableBindings(self.view,_testView1,_testView2,_testView3);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[_testView1(==_testView2)]-10-[_testView2]-10-|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[_testView1(<=700)]-10-[_testView3]-10-|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[_testView2(<=700)]-10-[_testView3]-10-|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-10-[_testView3]-10-|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_testView3(==150)]-10-|" options:0 metrics:0 views:views]];
}
2.Masonry的使用
mas_makeConstraints 是給view添加約束,約束有幾種,分別是邊距,寬,高,左上右下距離,基準線。添加過約束後可以有修正,修正有offset(位移)修正和multipliedBy(倍率)修正。
語法一般是 make.equalTo or make.greaterThanOrEqualTo or make.lessThanOrEqualTo + 倍數和位移修正。
註意點1: 使用 mas_makeConstraints方法的元素必須事先添加到父元素的中,例如[self.view addSubview:view];
註意點2: masequalTo 和 equalTo 區別:masequalTo 比equalTo多了類型轉換操作,一般來說,大多數時候兩個方法都是 通用的,但是對於數值元素使用mas_equalTo。對於對象或是多個屬性的處理,使用equalTo。特別是多個屬性時,必須使用equalTo,例如 make.left.and.right.equalTo(self.view);
註意點3: 註意到方法with和and,這連個方法其實沒有做任何操作,方法只是返回對象本身,這這個方法的左右完全是為了方法寫的時候的可讀性 。make.left.and.right.equalTo(self.view);和make.left.right.equalTo(self.view);是完全一樣的,但是明顯的加了and方法的語句可讀性更好點。
// exp1: 中心點與self.view相同,寬度為400*400
-(void)exp1{
UIView *view = [UIView new];
[view setBackgroundColor:[UIColor redColor]];
[self.view addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.size.mas_equalTo(CGSizeMake(400,400));
}];
}
//exp2: 上下左右邊距都為10
-(void)exp2{
UIView *view = [UIView new];
[view setBackgroundColor:[UIColor redColor]];
[self.view addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
// make.left.equalTo(self.view).with.offset(10);
// make.right.equalTo(self.view).with.offset(-10);
// make.top.equalTo(self.view).with.offset(10);
// make.bottom.equalTo(self.view).with.offset(-10);
}];
}
//exp3 讓兩個高度為150的view垂直居中且等寬且等間隔排列 間隔為10
-(void)exp3{
UIView *view1 = [UIView new];
[view1 setBackgroundColor:[UIColor redColor]];
[self.view addSubview:view1];
UIView *view2 = [UIView new];
[view2 setBackgroundColor:[UIColor redColor]];
[self.view addSubview:view2];
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.view.mas_centerY);
make.height.mas_equalTo(150);
make.width.mas_equalTo(view2.mas_width);
make.left.mas_equalTo(self.view.mas_left).with.offset(10);
make.right.mas_equalTo(view2.mas_left).offset(-10);
}];
[view2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.view.mas_centerY);
make.height.mas_equalTo(150);
make.width.mas_equalTo(view1.mas_width);
make.left.mas_equalTo(view1.mas_right).with.offset(10);
make.right.equalTo(self.view.mas_right).offset(-10);
}];
}