VFL是 Visual format language (可視格式語言)的縮寫,是Apple針對 AutoLayout 設計的一種語言。經過VFL,咱們能在代碼中靈活的使用AutoLayout而作到真正的不受設備控制!php
先看一個圖形:
html
它表明了有兩個button ,cancel 和 accept,他們的位置關係是左右相隔一段距離。api
將他們用簡單的方式畫出來,變成了下述圖:app
將其再次簡化,變成了以下一種格式:ide
而VFL正正是用上圖這樣的一種直觀的格式來展示約束的。佈局
不妨先看一下上述佈局用VFL的代碼實現,假設cancelButton和acceptButton相隔30像素,那麼爲兩個button添加約束的代碼爲:ui
NSDictionary* views = NSDictionaryOfVariableBindings( cancelButton,acceptButton);//肯定約束成員 NSArray *constraint = [NSLayoutConstraint constraintsWithVisualFormat:@"[cancelButton]-30-[acceptButton]" options:0 metrics:nil views:views]];//添加布局 [self.view addConstraints:constraint];//在視圖上添加約束
這樣的一個代碼就實現了上述約束的佈局。有些人確定會說,太麻煩了,還不如在sb上隨便點兩下。這個,確實是的。可是,當用sb沒法一次性知足N個設備時,VFL就發揮出它的頑強精神了!url
/****************************************************************/spa
「|: 」表示父視圖 eg:.net
@"|-[cancelButton]-30-[acceptButton]"
表示 cancelButton在父視圖的左邊緣(與父視圖的相對位置是 x = 0),常見的有:
1.|-[view]-|: 視圖處在父視圖的左右邊緣內
2.|-[view] : 視圖處在父視圖的左邊緣
3.|[view] : 視圖和父視圖左邊對齊;
/****************************************************************/
「-:」表示距離,eg:
@"[cancelButton(50)]-30-[acceptButton]"
表示cancelButton長50像素 和acceptButton的間隔是30像素
@"|-50-[cancelButton]"
表示cancelButton 離superView的左邊緣爲50個像素;
/****************************************************************/
V: :表示垂直
@"V:|-100-[cancelButton]-20-[acceptButton]"
表示cancelButton離父視圖頂端100個像素點,離accpetButton20個像素點
@"V:[acceptButton(300)]-20-|"
表示acceptButton高300像素,離superView底端有20個像素點;
/****************************************************************/
H: 表示水平(能夠不寫,默認的話就是水平位置);
/****************************************************************/
>= :表示視圖間距、寬度和高度必須大於或等於某個值;
<= :表示視圖間距、寬度和高度必須小宇或等於某個值;
== :表示視圖間距、寬度或者高度必須等於某個值 ;
@"V:|-(==padding)-[imageView]->=0-[button]-(==padding)-|"
表示離父視圖的距離爲Padding,這兩個視圖間距必須大於或等於0而且距離底部父視圖爲 padding。
@"[wideView(>=30@500)]"
表示視圖的寬度爲至少爲30 不能超過 500
若是想用autolayout,那麼必須先設置translatesAutoresizingMaskIntoConstraints爲NO
例如初始化一個UIButton類對象,那麼:
UIButton* cancelButton = [[UIButton alloc] init]; cancelButton.translatesAutoresizingMaskIntoConstraints = NO;
- (void)addConstraints:(NSArray *)constraints; + (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
參數介紹:
format:此參數爲你的vfl語句,好比:@"H:|-[button]-|"
opts:枚舉參數,默認寫0,具體跟據你所實現的需求去選擇你想要的枚舉
metrics:這裏是一個字典,當在format中使用了動態數據好比上現這句:@"H:|-[button(==width)]-|",表示這個button的寬度爲width,那麼這個參數去哪裏找呢?就是在這個字典裏面找到key對就的值,若是沒有找到這個值,app就會crash.
views:顧名思義,這是傳全部你在vfl中使用到的view,那在上面這句例子中的應該怎麼傳呢?結果是這樣的:NSDictionaryOfVariableBindings(button).若是你使用到了多個view,就能夠這樣NSDictionaryOfVariableBindings(button,button1,button3...),這個名字也要跟參數format中的一一對應,缺一不可.
/*---------------------------初始化----------------------------------*/ UIButton* cancelButton = [[UIButton alloc] init]; cancelButton.translatesAutoresizingMaskIntoConstraints = NO; UIButton* acceptButton = [UIButton new]; acceptButton.translatesAutoresizingMaskIntoConstraints = NO; /*------------------------------添加水平和垂直約束-------------------------*/ NSDictionary* views = NSDictionaryOfVariableBindings(cancelButton, acceptButton); NSString *vflString = [NSString stringWithFormat:@"|-20-[cancelButton(>=%d)]-20-|", self.view.frame.size.width/3]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vflString options:0 metrics:nil views:views]]; vflString = @"V:|-30-[cancelButton(150)]-15-[acceptButton(50)]"; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vflString options:0 metrics:nil views:views]];
- (void)addConstraint:(NSLayoutConstraint *)constraint
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
/*---------------------------初始化----------------------------------*/ UIButton* acceptButton = [UIButton new]; acceptButton.translatesAutoresizingMaskIntoConstraints = NO; NSDictionary* views = NSDictionaryOfVariableBindings(acceptButton); /*------------------------------acceptButton水平居中-------------------------*/ [self.view addConstraint:[NSLayoutConstraint constraintWithItem:acceptButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:acceptButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
注意:在上述例子中,acceptButton.attribute = self.view.attribute * multiplier + constant
附上兩張圖來回憶一下:
下面用代碼實現:
- (void)viewDidLoad { [super viewDidLoad]; UIView *view1 = [UIView new]; view1.translatesAutoresizingMaskIntoConstraints = NO; view1.backgroundColor = [UIColor redColor]; [self.view addSubview:view1]; UIView *view2 = [UIView new]; view2.translatesAutoresizingMaskIntoConstraints = NO; view2.backgroundColor = [UIColor orangeColor]; [self.view addSubview:view2]; UIView *view3 = [UIView new]; view3.translatesAutoresizingMaskIntoConstraints = NO; view3.backgroundColor = [UIColor yellowColor]; [self.view addSubview:view3]; UIView *view4 = [UIView new]; view4.translatesAutoresizingMaskIntoConstraints = NO; view4.backgroundColor = [UIColor cyanColor]; [self.view addSubview:view4]; UIView *view5 = [UIView new]; view5.translatesAutoresizingMaskIntoConstraints = NO; view5.backgroundColor = [UIColor greenColor]; [self.view addSubview:view5]; UIView *view6 = [UIView new]; view6.translatesAutoresizingMaskIntoConstraints = NO; view6.backgroundColor = [UIColor blueColor]; [self.view addSubview:view6]; UIView *view7 = [UIView new]; view7.translatesAutoresizingMaskIntoConstraints = NO; view7.backgroundColor = [UIColor purpleColor]; [self.view addSubview:view7]; NSDictionary *views = NSDictionaryOfVariableBindings(view1,view2,view3,view4,view5,view6,view7); /*---------------------view4居中顯示,長度以及寬度爲65-------------------------*/ [self.view addConstraint:[NSLayoutConstraint constraintWithItem:view4 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:view4 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[view4(65)]" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view4(65)]" options:0 metrics:nil views:views]]; /*---------------------View3長度寬度爲65,垂直居中,且它離容器左邊的距離爲一個固定值-------------------------*/ [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view3(65)]" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-13-[view3(65)]" options:0 metrics:nil views:views]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:view3 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; /*---------------------view5長度寬度爲65,垂直居中,且它離容器右邊的距離爲一個固定值-------------------------*/ [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view5(65)]" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[view5(65)]-13-|" options:0 metrics:nil views:views]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:view5 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; /*---------view1和view2 讓他離下面的最近的view 的距離以及根視圖的左邊或右邊的位置成固定值-------------*/ //view1 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view1(==65)]-69-[view3]" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-52-[view1(65)]" options:0 metrics:nil views:views]]; //view2 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view2(==65)]-69-[view5]" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[view2(65)]-52-|" options:0 metrics:nil views:views]]; /*---------view6和view7 讓他離上面的最近的view 的距離以及根視圖的左邊或右邊的位置成固定值-------------*/ //view6 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view3]-69-[view6(==65)]" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-52-[view6(65)]" options:0 metrics:nil views:views]]; //view7 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view5]-69-[view7(65)]" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[view7(65)]-52-|" options:0 metrics:nil views:views]]; }