iOS自動布局(Autolayout)之VFL(可視化格式語言)

2



作為一個移動端的程序員熬苍,布局永遠都是需要打交道的東西,最初剛入門那會郁季,用的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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坪圾,隨后出現(xiàn)的幾起案子晓折,更是在濱河造成了極大的恐慌,老刑警劉巖兽泄,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漓概,死亡現(xiàn)場離奇詭異,居然都是意外死亡病梢,警方通過查閱死者的電腦和手機胃珍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜓陌,“玉大人觅彰,你說我怎么就攤上這事∨ト龋” “怎么了填抬?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長隧期。 經常有香客問我飒责,道長,這世上最難降的妖魔是什么仆潮? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任宏蛉,我火速辦了婚禮,結果婚禮上鸵闪,老公的妹妹穿的比我還像新娘檐晕。我一直安慰自己,他們只是感情好蚌讼,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布辟灰。 她就那樣靜靜地躺著,像睡著了一般篡石。 火紅的嫁衣襯著肌膚如雪芥喇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天凰萨,我揣著相機與錄音继控,去河邊找鬼械馆。 笑死,一個胖子當著我的面吹牛武通,可吹牛的內容都是我干的霹崎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冶忱,長吁一口氣:“原來是場噩夢啊……” “哼尾菇!你這毒婦竟也來了?” 一聲冷哼從身側響起囚枪,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤派诬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后链沼,有當地人在樹林里發(fā)現(xiàn)了一具尸體默赂,經...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年括勺,在試婚紗的時候發(fā)現(xiàn)自己被綠了缆八。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡朝刊,死狀恐怖耀里,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情拾氓,我是刑警寧澤冯挎,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站咙鞍,受9級特大地震影響房官,放射性物質發(fā)生泄漏。R本人自食惡果不足惜续滋,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一翰守、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧疲酌,春花似錦蜡峰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至粥诫,卻和暖如春油航,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怀浆。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工谊囚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留怕享,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓镰踏,卻偏偏與公主長得像函筋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子奠伪,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內容