作為一個移動端的程序員熬苍,布局永遠都是需要打交道的東西,最初剛入門那會郁季,用的storyboard,xib手動拖拽的方式設置約束冷溃,看起來是直觀了,但是費時又費力還吃力不討好梦裂,感覺還是沒有純純的代碼好用似枕。
代碼約束最初還是靠本人機密的計算,算比例算數值各種算年柠,約束是沒問題了凿歼,時間浪費了很多,計算能力倒是增強了不少 T-T冗恨。答憔。。掀抹。虐拓。。傲武。蓉驹。
后來我發(fā)現(xiàn)了個好東西
UIView *v1 = [[UIView alloc] initWithFrame:CGRectZero];
v1.translatesAutoresizingMaskIntoConstraints = NO;
v1.backgroundColor = [UIColor redColor];
[self.view addSubview:v1];
UIView *v2 = [[UIView alloc] initWithFrame:CGRectZero];
v2.backgroundColor = [UIColor grayColor];
v2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:v2];//添加兩個允許自動布局的子視圖
[self.viewaddConstraint:[NSLayoutConstraint constraintWithItem:v1attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.viewattribute:NSLayoutAttributeHeight multiplier:0.5constant:0]];//設置子視圖的高度是父視圖高度的一半
大致就是這樣一種約束形式,是不是覺得很長揪利,而且沒有注釋的話一眼還看不出來是哪哪的約束态兴,于是我又找了找,發(fā)現(xiàn)了這個
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? VFL
Visual Format Language疟位,簡稱VFL 即“可視化格式語言”瞻润。
VFL是一種聲明性語言,VFL允許您通過一個格式化后的代碼字符串迅速定義視圖的自動布局約束
他給人的感覺就是直觀,因為你會發(fā)現(xiàn)很多的這個
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? H:|-20-[view1]-30-[view2(==view1)]-20-|
看到這個是不是蒙圈了绍撞,不要急正勒,其實這東西還是蠻簡單的,慢慢看看規(guī)則一學就會了楚午,接下來我就快速的解釋一下
首先
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary*)metrics views:(NSDictionary*)views;
運用這個api就能簡單實現(xiàn)約束了昭齐,當然VFL還是要寫的
format? 格式規(guī)范的約束。
opts?????? 描述VFL中的所有對象的屬性和布局的方向 矾柜。
metrics? 一個字典阱驾,字典的key必須是在VFL字符串中被使用的字符串,值必須是NSNumber對象
views?? ? 出現(xiàn)在在VFL字符串中的視圖組成的字典怪蔑, 字典的key必須是在VFL字符串中被使用的字符串里覆。并且其值必須是一個View對象
先來一段代碼
_view1= [[UIViewalloc]init];
_view1.backgroundColor= [UIColorwhiteColor];
_view1.translatesAutoresizingMaskIntoConstraints=NO;
_view2= [[UIViewalloc]init];
_view2.backgroundColor= [UIColorgreenColor];
_view2.translatesAutoresizingMaskIntoConstraints=NO;
UIView*view4 = [[UIViewalloc]init];
view4.backgroundColor= [UIColorpurpleColor];
view4.translatesAutoresizingMaskIntoConstraints=NO;
[self.viewaddSubview:_view1];
[self.viewaddSubview:_view2];
self.view.backgroundColor= [UIColorgrayColor];
UIView*view1 =_view1;
UIView*view2 =_view2;
NSDictionary*bindings =NSDictionaryOfVariableBindings(view1,view2);
NSArray*constraints=[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|-20-[view1]-30-[view2(==view1)]-20-|"options:0metrics:nilviews:bindings];
NSArray*constraints2=[NSLayoutConstraintconstraintsWithVisualFormat:@"V:|-20-[view1(40)]"options:0metrics:nilviews:NSDictionaryOfVariableBindings(view1)];
NSArray*constraints3=[NSLayoutConstraintconstraintsWithVisualFormat:@"V:|-20-[view2(40)]"options:0metrics:nilviews:NSDictionaryOfVariableBindings(view2)];
[self.viewaddConstraints:constraints];
[self.viewaddConstraints:constraints2];
[self.viewaddConstraints:constraints3];
效果是這樣的
屏幕怎么轉我的控件在我的控制之中這就是VFL的方便之處,哈哈缆瓣、喧枷。
解釋開始:
VFL 語法
(<方向>:)?(<父視圖前><連接>)?[<被布局視圖>]9搿(<連接><其他視圖>)*(<連接><父視圖后>)隧甚?
1???????????????????????????????? 2 ? ? ? ? ? ? ? ? ? ? ? ? ? ?3 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?4 ? ? ? ? ? ? ? ? ? ? ? ?5
?問號指的是一個可選項渡冻,不是必需的戚扳。*指的是該項會出現(xiàn)0次或者多次。族吻!代表必需指定
雖然該定義看上去令人生畏帽借,但是事實上這些字符串相當容易構建。
例如:
“H:|-[view1]-[view2]-(>=8)-[view3]-|”
VFL格式字符串:
1.方向:約束在坐標軸上的方向超歌。H代表水平方向排列砍艾,V代表垂直方向排列,不指定代表默認值水平方向
2.父視圖前:關聯(lián)到父視圖前邊緣巍举。 垂直方向上的被布局視圖頂部邊緣與父視圖頂部邊緣的距離脆荷,水平方向上的被布局視圖前邊緣與父視圖前邊緣的距離
3.被布局視圖:你添加layout的視圖。
4.其他視圖:被布局視圖關聯(lián)的另外一個視圖
5.父視圖后:關聯(lián)到父視圖后邊緣懊悯。垂直方向上的被布局視圖底部邊緣與父視圖底部邊緣的距離简烘,水平方向上的被布局視圖后邊緣與父視圖后邊緣的距離
視圖名稱
視圖的名稱被一對方括號包圍,例如你可以使用[thisView],[thatView]定枷。當使用變量綁定字典時,視圖的名稱指的是本地變量名届氢。
父視圖
總是用一個特殊的字符 豎線“|”欠窒,來表示父視圖,僅會在VFL的開頭或者結尾出現(xiàn)。在開頭時候岖妄,它恰好出現(xiàn)在水平或者垂直方向指定符之后(“V:|”或者“H:|”)型将。在結尾時,它恰好出現(xiàn)在引號之前(“.....|”)荐虐。
無需在綁定字典中命名父視圖七兜。AutoLayout知道“|”代表父視圖。
使用父視圖的典型包括:
延伸一個視圖來適應它的父視圖福扬,例如“H:|[view]|”
將一個視圖偏離它的父視圖的某條變腕铸,例如“V:[view]-8-”
創(chuàng)建一列或一行與父視圖對齊的視圖,例如“V:[view1]-[view2]-[view3]-[view4]”
連接
連接指定視圖直接的間隔铛碑。每個視圖(包括父視圖的引用)間的連接標明了要添加的間距狠裹。
空連接
空連接看起來像“ H:[view1][view2]”,在每個視圖的方括號直接沒有任何符號,沒有指定任何東西汽烦,顯示效果將是兩個視圖僅僅的貼在了一起
標準間隔
連接符 - 代表一個標準的固定間隔涛菠,比如“ H:[view1]-[view2]”,每個視圖直接增加了一個小的間隙撇吞,盡管官方并沒有文檔化俗冻,但標準間隔一般對于視圖到視圖布局為8點,對于視圖到父視圖為20點牍颈。標準間隔確保相關聯(lián)但是又完全分離的視圖以足夠的視覺間隔顯示迄薄。
數字間隔
可以在兩個方括號直接使用一對連字符中間夾著數字來設置準確的間隔大小,約束“ H:[view1]-30-[view2]”在兩個視圖之間增加了一個30點的間隔颂砸。
引用父視圖
格式“ H:|[view1]-[view2]|”確定了以父視圖開頭的水平布局噪奄。父視圖后緊跟的是第一個視圖,然后是一個間隔和第二個視圖人乓,之后是一個豎線符也就是是父視圖勤篮。
與父視圖的間隔
格式“ H:|-[view1]-[view2]-|”為前后邊緣到父視圖,每個增加了一個標準間隔 20點
格式“ H:|[view1]-[view2]-50-|”為后邊緣到父視圖色罚,增加了一個自定義間隔 50點
靈活間隔
如果是目標是在視圖間添加一個靈活間隔碰缔,同也有辦法。為兩個視圖添加一個關系規(guī)則(例如“H:|-[view1]-(>=0)-[view2]-|”)戳护,允許這兩個視圖保持他們的尺寸金抡,在維護他們的邊緣同父視圖的間隔時將他們分離出來。
這個規(guī)則可以讀作“至少0點間距”腌且,提供了使視圖分開的更靈活的方式梗肝。
當說“至少50點”(>50 )或者“不超過30帶你”(<=30)時,不能將間距和標準間隔結合起來是有铺董。例如>=-巫击,<=1是非法的。你只能使用等值數值。記住坝锰,標準的視圖到時間間隔是8點粹懒,而視圖到父視圖的間隔是20帶你。
圓括號
為了清晰可見顷级,關系(>=0)被放在一堆括號中凫乖,括號將非常簡單的正數或者負數或者度量名間隔區(qū)分開來
在如何表達規(guī)則時,你可以對可視化約束有很大的靈活性弓颈。如下規(guī)則都實現(xiàn)兩個相互眥鄰的視圖:
[view1][view2]
[view1]-0-[view2]
[view1]-(0)-[view2]
[view1]-(==0)-[view2]
[view1]-(>=0,<=0)-[view2]
[view1]-(==0@1000)-[view2]
[view1]-(>=0,<=0,<=30)-[view2]
當在括號中添加多個關系時帽芽,使用逗號分隔各項。符號@表示一個優(yōu)先級
負數
比如為任何使用負數值的間隔加上括號恨豁。如下約束是非法的:
V:[view1]--5-[view2]
負數在可視化約束中是允許的嚣镜,正確寫法
V:[view1]-(-5)-[view2]
優(yōu)先級
在任何連接或者尺寸規(guī)則后拼接一個@符號,@符號后是一個想要設置的優(yōu)先級橘蜜。為了清晰可見菊匿,最好將其使用圓括號括起來
例如:
“H:|-(5@20)[view1]-[view2]-|”
間隔規(guī)則優(yōu)先級默認是必須的(值為1000),因為將優(yōu)先級降到了20计福,所以兩個視圖改變尺寸的方式可以能會影響布局跌捆。
多視圖
格式視圖并不局限于一個或者兩個視圖,我可以很容易的插入第三個象颖,第四個或者更多佩厚。
“H:|-[view1]-[view2]-(>=8)-[view3]-|”
視圖尺寸
VFL除了可以用方括號分隔視圖名稱外,還可以在方括號中指定視圖的尺寸说订〕撸可以在名稱之后的圓括號里指定值,例如:
可以指定一個視圖的寬度為120點固定值:“H:[view1(120)]”陶冷。如果你喜歡顯示的說明關系钙姊,也可以添加這樣的格式“H:[view1(==120)]”
可以指定一個視圖的寬度至少50點,使用如下約束:“H:[view1(>=50)]”,50-70點之間“H:[view1(>=50埂伦,<=70)]”
可以引用其他視圖指定尺寸:”H:|[view1(view2)-[view2]-|]“,因為約束是無方向的煞额,所以可以自我引用,可以使用如下方式創(chuàng)建一個相等布局:”H:|[view1(view2)-[view2(view2)]-|]“,循環(huán)定義不會產生性能損失沾谜。
不是所有視圖都需要參與尺寸匹配膊毁。一個請求可以圍繞一個基本視圖創(chuàng)建側翼視圖
視圖尺寸也可以表示優(yōu)先級。在格式化字符串“H:|[view1(==250@700)]-[view2(==250@701)]-|”中基跑,view1和view2都請求寬度為250點婚温,view2獲勝,因為他的請求有更大的優(yōu)先級媳否,所以首先拉伸view2
盡管可以很容易地在代碼中使用乘數來創(chuàng)建表達相對尺寸的約束缭召,但是無法在可視化約束中那樣做栈顷。這是一個非法約束::”H:|[view1==2*view2]-[view2]-|“。如果想說“view1寬度是view2的兩倍”嵌巷,就需要在代碼中實現(xiàn)
看的好暈,好吧其實我也做了個小demo室抽,順便放了很多其它東西搪哪,如果覺得有用可以自己下載
VFLDemo:https://github.com/taosiyu/TSYVFLDemo
可以的話給個star