iOS自動布局
1 autoresizing
autoresizingMask:創(chuàng)建視圖的同時給出其相對于父視圖的“對齊方式與縮放系數(shù)”静稻。當父視圖發(fā)生變化時,通過每個子視圖的autoresizingMask即可自動得出新的位置匈辱,而無需開發(fā)者提供振湾。
缺點:
- 其描述界面變化規(guī)則不夠靈活,很多變化規(guī)則根本無法精確描述亡脸。autoresizingMask縮放比例是UIKit內(nèi)部計算的押搪,開發(fā)者無法指定縮放比例的精確值。
- 變化規(guī)則只能基于父視圖與子視圖之間浅碾,無法建立同級視圖或者跨級視圖之間的關(guān)系嵌言。
樣例:
- (void)viewDidLoad {
[super viewDidLoad];
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
containerView.backgroundColor = [UIColor blueColor];
[self.view addSubview:containerView];
UILabel *text = [[UILabel alloc] initWithFrame:CGRectZero];
text.text = @"1231312";
[containerView addSubview:text];
text.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth;
text.frame = CGRectMake(0, 0, containerView.bounds.size.width - 20, 100);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
containerView.frame = CGRectMake(0, 0, 300, 200);
NSLog(@"%@ %@ %@ %@", @(text.frame.origin.x), @(text.frame.origin.y), @(text.frame.size.width),
@(text.frame.size.height));
});
}
2 autolayout
autolayout:它允許開發(fā)者在界面上的任意兩個視圖之間建立精確的線性變化規(guī)則。所謂線性變化就是數(shù)學中的一次函數(shù)及穗,即:y = m*x + c,其中x和y是界面中任意兩個視圖的某個布局屬性,m為比例系數(shù)绵载,c為常量埂陆。每個線性變化規(guī)則稱之為布局約束(Layout Constraint)。
2.1 NSLayoutConstraint
NS_CLASS_AVAILABLE_IOS(6_0)
@interface NSLayoutConstraint : NSObject
...
@property (readonly, assign) id firstItem;
@property (readonly) NSLayoutAttribute firstAttribute;
@property (readonly) NSLayoutRelation relation;
@property (readonly, assign) id secondItem;
@property (readonly) NSLayoutAttribute secondAttribute;
@property (readonly) CGFloat multiplier;
@property CGFloat constant;
...
+(instancetype)constraintWithItem:(id)firstItem attribute:(NSLayoutAttribute)firstAttribute
relatedBy:(NSLayoutRelation)relation
toItem:(id)secondItem attribute:(NSLayoutAttribute)secondAttribute
multiplier:(CGFloat)multiplier constant:(CGFloat)constant;
公式:firstItem.firstAttribute {==,<=,>=} secondItem.secondAttribute * multiplier + constant
解釋:firstItem與secondItem分別是界面中受約束的視圖與被參照的視圖娃豹。他們不一定非得是兄弟關(guān)系或者父子關(guān)系焚虱,只要是他們有著共同的祖先視圖即可,這一點是autoresizingMask無法做到的懂版。
fir
stAttribute與secondAttribute分別是firstItem與secondItem的某個布局屬性(NSLayoutAttribute)鹃栽。注意,firstItem與secondItem不一定非得是同樣的值躯畴,允許定義諸如某視圖的高度等于另一個視圖的寬度這樣的約束
民鼓。NSLayoutAttributeNotAnAttribute這個額外解釋一下薇芝,當我們需要為某個視圖精確指定一個寬度或者高度值時,這時候secondItem為nil丰嘉,secondAttribute為NSLayoutAttributeNotAnAttribute夯到。relation定義了布局關(guān)系(NSLayoutRelation)。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView *v1 = [UIView new];
v1.backgroundColor = [UIColor blueColor];
v1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:v1];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:v1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1
constant:0];
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:v1
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:1
constant:0];
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:v1
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeRight
multiplier:1
constant:0];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:v1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0];
// iOS8 以下
// [v1 addConstraint:topConstraint];
// [v1 addConstraint:leftConstraint];
// [v1 addConstraint:rightConstraint];
// [v1 addConstraint:heightConstraint];
// iOS8及以上
topConstraint.active = YES;
leftConstraint.active = YES;
rightConstraint.active = YES;
heightConstraint.active = YES;
}
2.2 VFL
2.3 自身內(nèi)容尺寸約束饮亏、修改約束耍贾、布局動畫
自身內(nèi)容尺寸約束:一般來說,要確定一個視圖的精確位置路幸,至少需要4個布局約束(以確定水平位置x荐开、垂直位置y、寬度w和高度h)简肴。但是晃听,某些用來展現(xiàn)內(nèi)容的用戶控件,例如文本控件UILabel着帽、按鈕UIButton杂伟、圖片視圖UIImageView等域那,它們具有自身內(nèi)容尺寸(Intrinsic Content Size)墓律,此類用戶控件會根據(jù)自身內(nèi)容尺寸添加布局約束。也就是說胃夏,如果開發(fā)者沒有顯式給出其寬度或者高度約束予借,則其自動添加的自身內(nèi)容約束將會起作用越平。因此看似“缺失”約束,實際上并非如此灵迫。
對于約束的如下幾個重要屬性:
@property (readonly, assign) id firstItem;
@property (readonly) NSLayoutAttribute firstAttribute;
@property (readonly) NSLayoutRelation relation;
@property (readonly, assign) id secondItem;
@property (readonly) NSLayoutAttribute secondAttribute;
@property (readonly) CGFloat multiplier;
/* Unlike the other properties, the constant may be modified after constraint creation. Setting the constant on an existing constraint performs much better than removing the constraint and adding a new one that's just like the old but for having a new constant.
*/
@property CGFloat constant;
更新約束:
當使用代碼來修改約束時秦叛,只能修改約束的常量值constant。一旦創(chuàng)建了約束瀑粥,其他只讀屬性都是無法修改的挣跋,特別要注意的是比例系數(shù)multiplier也是只讀的。
添加刪除約束:
- (void)keyboardWillShow:(NSNotification *)notification
{
self.labelCenterYNormalCons.active = NO;
self.labelCenterYKeyboardCons.active = YES;
}
- (void)keyboardWillHide:(NSNotification *)notification
{
self.labelCenterYKeyboardCons.active = NO;
self.labelCenterYNormalCons.active = YES;
}
盡量先設(shè)置需要將active置為NO的約束狞换,然后再設(shè)置需要將active置為YES的約束避咆,如果顛倒上面兩條語句的話,可能會引起運行時約束錯誤修噪。
修改約束優(yōu)先級:
- (void)keyboardWillShow:(NSNotification *)notification
{
self.labelCenterYNormalCons.priority = UILayoutPriorityDefaultLow;
self.labelCenterYKeyboardCons.priority = UILayoutPriorityDefaultHigh;
}
- (void)keyboardWillHide:(NSNotification *)notification
{
self.labelCenterYKeyboardCons.priority = UILayoutPriorityDefaultLow;
self.labelCenterYNormalCons.priority = UILayoutPriorityDefaultHigh;
}
需要注意的是查库,只能修改可選約束的優(yōu)先級,也就是說:
- 不允許將優(yōu)先級由小于1000的值改為1000
- 不允許將優(yōu)先級由1000修改為小于1000的值
例如黄琼,如果將優(yōu)先級由250修改為1000樊销,則會拋出異常。
自身內(nèi)容尺寸約束的抗擠壓與抗拉抻效果
彈簧會有自身固有長度,當有外力作用時围苫,彈簧會抵抗外力作用裤园,盡量接近固有長度。
抗拉抻:當外力拉長彈簧時够吩,彈簧長度大于固有長度比然,且產(chǎn)生向內(nèi)收的力阻止外力拉抻,且盡量維持長度接近自身固有長度周循。
抗擠壓:當外力擠壓彈簧時强法,彈簧長度小于固有長度,且產(chǎn)生向外頂?shù)牧ψ柚雇饬D壓湾笛,且盡量維持長度接近自身固有長度饮怯。
對于自身內(nèi)容尺寸約束,Hug值表示抗拉抻優(yōu)先級嚎研,CompressionResistance值表示抗壓縮優(yōu)先級蓖墅。Hug值越高越難被拉抻,CompressionResistance值越高越難被壓縮临扮。這兩個都是針對自身內(nèi)容尺寸论矾。這兩個值越高,在自動布局的時候杆勇,view的真實布局就越接近自身內(nèi)容尺寸贪壳。他們表達的是一種自身內(nèi)容尺寸約束對外加約束的抵抗力。