VFL是蘋果推出的用來AutoLayout布局的一門比較形象的語言, 本身為字符串,雖然用起來比較麻煩, 但是相比直接使用蘋果的另一個(gè)套布局方案要少寫一些代碼, 那么問題來了, github上那么多自動(dòng)布局的框架, 簡單又好用, 為什么要用這么復(fù)雜的代碼去布局呢, 之前我也這么想, 直到有一天自己想封裝一個(gè)框架的的時(shí)候才發(fā)現(xiàn), 不能處處依賴別人的框架去封裝, 因?yàn)檫@樣的話, 你封裝的框架幾乎沒法用. 舉個(gè)例子, 假設(shè)你的框架用了AFN的2.0版本, 那么對(duì)于使用框架的人來說, 他們項(xiàng)目中如果使用了AFN3.0, 那么肯定出出現(xiàn)一大堆兼容問題, 因此對(duì)于自己的封裝的框架, 要以原生為主. 廢話不多說 下面總結(jié)一下我半天的的學(xué)習(xí)成果: VFL布局
下面是VFL使用的一個(gè)核心方法
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format
options:(NSLayoutFormatOptions)opts
metrics:(nullable NSDictionary<NSString *,id> *)metrics
views:(NSDictionary<NSString *, id> *)views;
該方法一共有四個(gè)參數(shù), 接下來將一一講解四個(gè)參數(shù)的含義及其使用:
- format參數(shù): 這個(gè)是具體布局的字符串,形如 @"V:|-10-[view1(50.0)]-20-[view2(50.0)]" 稍后再講解此字符串的意思;
- option參數(shù): 這個(gè)參數(shù)是一個(gè)可復(fù)選的參數(shù), 主要用來布局view的對(duì)齊方式;
- metrics參數(shù): 這個(gè)參數(shù)是替換VFL字符串中的變量用的, 如果這么寫: @{@"topMargin":@10} 則第一條中的布局可以替換成下面的寫法: @"V:|-10-[view1(50.0)]-20-[view2(50.0)]" 其實(shí)就是替換字符串中的變量使用;
- views參數(shù): 這個(gè)參數(shù)是用來存儲(chǔ)本條VFL語句中所有用到的View, 可以直接創(chuàng)建字典 @{@"view1":view1, @"view2":view2} 對(duì)于這個(gè)參數(shù)蘋果有一個(gè)特定的宏, NSDictionaryOfVariableBindings() 因此也可以這樣寫 NSDictionaryOfVariableBindings(view1, view2) ;
該方法返回的是一個(gè)裝有約束的數(shù)組集合;可以直接添加到設(shè)定約束view的父view上;
如果你對(duì)上面的解釋不太理解下面用代碼具體舉個(gè)列子,相信你立馬會(huì)恍然大悟
- (void)viewDidLoad {
[super viewDidLoad];
[self testConstraint];
}
- (void)testConstraint {//測試布局
UIView *supView1 = [[UIView alloc] init];
supView1.backgroundColor = [UIColor blueColor];
UIView *supView2 = [[UIView alloc] init];
supView2.backgroundColor = [UIColor blueColor];
[self.view addSubview:supView1];
[self.view addSubview:supView2];
//由于AutoLayout布局和Autoresizing布局是沖突的,因此要使用AutoLayout必須要關(guān)閉Autoresizing
self.view.translatesAutoresizingMaskIntoConstraints = NO;
supView2.translatesAutoresizingMaskIntoConstraints = NO;
supView1.translatesAutoresizingMaskIntoConstraints = NO;
//此語句的意思是 垂直方向: supView1距離父view的距離為 topMargin,
//supView1的垂直方向的寬度為50.0, supView2距離supView1為20, 并且高度也為50.0;
NSString *top = @"V:|-topMargin-[supView1(50.0)]-20-[supView2(50.0)]";
//解釋方法同上
NSString *left = @"H:|-10-[supView1(50.0)]";
NSString *v2T = @"[supView2(60.0)]";
//此處需要對(duì)topMargin參數(shù)進(jìn)行解釋, 其實(shí)就是給topMargin賦值;
NSArray *s1T = [NSLayoutConstraint constraintsWithVisualFormat:top options:NSLayoutFormatAlignAllRight metrics:@{@"topMargin":@100} views:NSDictionaryOfVariableBindings(supView1, supView2)];
NSArray *s1L = [NSLayoutConstraint constraintsWithVisualFormat:left options:0 metrics:nil views:NSDictionaryOfVariableBindings(supView1)];
NSArray *v2Tc = [NSLayoutConstraint constraintsWithVisualFormat:v2T options:0 metrics:nil views:NSDictionaryOfVariableBindings(supView2)];
//一般需要把約束添加到父view上
[self.view addConstraints:v2Tc];
[self.view addConstraints:s1T];
[self.view addConstraints:s1L];
}
效果如下圖:
上面的例子只是簡單的使用了一下VFL語句, 其實(shí)還有更多的東西, 需要自己去慢慢的理解體會(huì)多使用, 熟練了就好了, 對(duì)于其他的VFL語句的用法請(qǐng)參考附錄里面的詳細(xì)使用
附錄
-
符號(hào)含義
|: 表示父視圖 -: 表示距離 V: 表示垂直 H: 表示水平 >=: 表示視圖間距欲虚、寬度和高度必須大于或等于某個(gè)值 <= :表示視圖間距、寬度和高度必須小宇或等于某個(gè)值 == :表示視圖間距植旧、寬度或者高度必須等于某個(gè)值 @: 優(yōu)先級(jí) 最大為 1000
-
一般用法:
|-[view]-|: 視圖處在父視圖的左右邊緣內(nèi) |-[view] : 視圖處在父視圖的左邊緣 |[view] : 視圖和父視圖左邊對(duì)齊 V:[view(100.)] : 設(shè)置視圖的高度 H:[view(100.)] : 設(shè)置視圖的寬度 |-30.0-[view]-30.0-|: 表示離父視圖 左右間距 30 |-[view(view1)]-[view1]-| : View和view1視圖寬度一樣耕姊,并且在父視圖內(nèi) V:|-padding-[imageView]->=0-[button]-padding| : 表示離父視圖的距離為Padding,這兩個(gè)視圖間距必須大于或等于0并且距離底部父視圖為padding。此時(shí)必須對(duì) metrics參數(shù)賦值eg. metrics:@{@"topMargin":@100}; [wideView(>=60@700)] :視圖的寬度為至少為60 優(yōu)先級(jí)為700 最后要注意, H可以忽略, 默認(rèn)為水平布局 , V必須要寫!!!
?
好了碼了半天終于大功告成, 希望此博客對(duì)你有幫助, 記得點(diǎn)贊哦~