AutoLayout 使用之代碼實現(VFL)

1、什麼是VFL?

     VFL是 Visual format language (可視格式語言)的縮寫,是Apple針對 AutoLayout 設計的一種語言。經過VFL,咱們能在代碼中靈活的使用AutoLayout而作到真正的不受設備控制!php

2、VFL的圖形表示

先看一個圖形:
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

3、VFL的使用規則

/****************************************************************/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


4、VFL使用的前提和方法

一、設置translatesAutoresizingMaskIntoConstraints屬性

若是想用autolayout,那麼必須先設置translatesAutoresizingMaskIntoConstraints爲NO

例如初始化一個UIButton類對象,那麼:

    UIButton* cancelButton = [[UIButton alloc] init];
    cancelButton.translatesAutoresizingMaskIntoConstraints = NO;


二、兩種經常使用的約束格式(NSArray、NSLayoutConstraint

(1)NSArray方法(適用於添加水平和垂直的約束)

- (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]];



      

(2) NSLayoutConstraint (適用於添加居中的約束)

- (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



5、代碼實現上篇博客中storyboard的佈局AutoLayout 使用之storyboard演示

附上兩張圖來回憶一下:


下面用代碼實現:

- (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]];

}
相關文章
相關標籤/搜索