制作一个类似苹果VFL的格式化语言来描述UIStackView
在項(xiàng)目中總是希望頁面上各處的文字,顏色,字體大小甚至各個(gè)視圖控件布局都能夠在發(fā)版之后能夠修改以彌補(bǔ)一些前期考慮不周,或者根據(jù)統(tǒng)計(jì)數(shù)據(jù)能夠隨時(shí)進(jìn)行調(diào)整,當(dāng)然是各個(gè)版本都能夠統(tǒng)一變化??吹竭@樣的要求后,第一反應(yīng)是這樣的頁面只能改成H5,或者嘗試使用React Native來應(yīng)對這種要求。
?
既然UIStackView已經(jīng)提供了一種既先進(jìn)又簡潔的布局思路,為何不通過制作一個(gè)類似VFL這樣的DSL語言來處理布局。這樣不就能夠通過下發(fā)一串DSL字符串的方式來進(jìn)行內(nèi)容樣式甚至布局的更換,不用跟版,還能使多版本統(tǒng)一。同時(shí)在端內(nèi)直接用這樣的DSL語言來寫界面不光能夠減少代碼量易于維護(hù),還能夠很直觀方便的看出整個(gè)界面布局結(jié)構(gòu)。
?
AssembleView(組裝視圖)和PartView(零件視圖)
?
在設(shè)計(jì)格式化語言之前需要對布局做個(gè)統(tǒng)一思想進(jìn)行管理,在看了WWDC里關(guān)于UIStackView的介紹后感覺任何復(fù)雜的布局都能夠通過這樣一種組合排布再組合排布的思路特別適合用格式化語言來描述。于是我想出兩個(gè)視圖概念。
?
一個(gè)是AssembleView組合視圖,專門用于對其PartView子視圖進(jìn)行排列,比如說是水平排列還是垂直排列,PartView是按照居中對齊還是居左等對齊方式,各個(gè)PartView之間間隔是多少。
?
PartView決定自己視圖類型,內(nèi)容,無固定大小的可以設(shè)置大小,同時(shí)AssembleView可以作為PartView被加入另一個(gè)AssembleView里進(jìn)行排列,這樣各種設(shè)計(jì)圖都可以在初期通過拆解分成不同的AssembleView和PartView進(jìn)行組合套組合布局出來。
?
格式化語言
?
接下來是如何通過格式化語言來描述AssembleView和PartView?!皗}”符號里包含的是AssembleView的設(shè)置,“[]”符號里是PartView的設(shè)置,“()”里是他們的屬性設(shè)置,“”可以將對象帶入到設(shè)置里。下面舉幾個(gè)例子說明下。完整Demo放到了Github上:https://github.com/ming1016/STMAssembleView
?
三個(gè)星星水平對齊居中排列
?
h表示水平排列horizontal,c表示居中center,“[]”PartView會根據(jù)順序依次添加排列,imageName屬性能夠指定本地圖片
?
?
三個(gè)星星水平對齊居中排列
?
{
????hc(padding:30)
????[(imageName:starmingicon)]
????[(imageName:starmingicon)]
????[(imageName:starmingicon)]
}
?
AssembleView里套作為PartView的AssembleView的復(fù)雜情況
?
color可以指定文字顏色,font指定文字大小
?
?
AssembleView里套作為PartView的AssembleView的復(fù)雜情況
?
{
????ht(padding:10)
????[avatarImageView(imageName:avatar)]
????[
????????{
????????????vl(padding:10)
????????????[(text:戴銘,color:AAA0A3)]
????????????[(text:Starming站長,color:E3DEE0,font:13)]
????????????[(text:喜歡畫畫編程和寫小說,color:E3DEE0,font:13)]
????????}
????????(width:210,backColor:FAF8F9,backPaddingHorizontal:10,backPaddingVertical:10,radius:8)
????]
}
?
給PartView設(shè)置背景色和按鈕
?
設(shè)置背景色使用backColor,背景距離設(shè)置的PartView的內(nèi)容間距通過backPaddingHorizontal屬性設(shè)置水平間距,backPaddingVertical設(shè)置垂直間距,“”符號帶入的button通過button屬性設(shè)置。
?
?
[
????{
????????hc(padding:4)
????????[(imageName:starmingicon,width:14,height:10)]
????????[(text:關(guān)注,font:16,color:FFFFFF)]
????}
????(height:36,backColor:AAA0A3,radius:8,backBorderWidth:1,backBorderColor:E3DEE0,backPaddingHorizontal:80,backPaddingVertical:10,button:)
]
?
AssembleView設(shè)置忽略約束的方法
?
水平排列時(shí),通過ignoreAlignment屬性設(shè)置忽略left約束,如果是垂直排列設(shè)置top忽略。
?
?
{
????hc(padding:5)
????[(text:STMAssembleView演示,color:E3DEE0,font:13)]
????[(imageName:starmingicon,width:14,height:10,ignoreAlignment:left)]
????[(text:Starming星光社,color:E3DEE0,font:13)]
}
?
將前面的視圖組合成一個(gè)AssembleView
?
?
將前面的視圖組合成一個(gè)AssembleView
?
ASS(@"{
????vc(padding:20)
????[%@(height:90)]
????[%@(height:36,backColor:AAA0A3,radius:8,backBorderWidth:1,backBorderColor:E3DEE0,backPaddingHorizontal:80,backPaddingVertical:10,button:)]
????[%@(height:25)]
????[%@(ignoreAlignment:top,isFill:1,height:16)]
}",midStr,followBtStr,centerStr,desStr)
?
AssembleView的屬性
?
-
當(dāng)在“{}”里面第一個(gè)字母是v表示垂直排列vertical,是h表示水平排列horizontal
-
第二個(gè)字母是c表示所有PartView居中對齊center,l表示居左對齊left,r表示居右對齊right,t表示居上對齊top,b表示居下對齊bottom。
-
padding:默認(rèn)各個(gè)PartView的間距。
?
PartView的屬性
?
-
如果不希望通過屬性生成視圖,可以通過在[后直接填入帶入對象對應(yīng)的key,然后再在()里設(shè)置屬性。
?
PartView布局相關(guān)屬性
?
-
width:UILabel和UIImage這樣有固定大小的可以不用設(shè)置,會按照固定大小的來。
-
height:有固定大小的可以不用設(shè)置。
-
isFill:垂直排列時(shí)會將寬設(shè)置為父AssembleView的寬,水平排列時(shí)會將高設(shè)置為父AssembleView的高。
-
padding:設(shè)置后會忽略父AssembleView里設(shè)置的padding,達(dá)到自定義間距的效果。
-
partAlignment:可以自定義對齊方向,設(shè)置后會忽略父AssembleView里設(shè)置的對齊。值可填center,left,right,top,bottom。
-
ignoreAlignment:設(shè)置忽略的約束方向,在父AssembleView不需要由子PartView決定大小的情況下,可以通過打斷某個(gè)方向約束來實(shí)現(xiàn)拆開排列的效果。值可填center,left,right,top,bottom。
?
PartView權(quán)重相關(guān)屬性
?
-
crp:Compression Resistance Priority的設(shè)置,根據(jù)權(quán)重由低到高值可以設(shè)置為fit,low,high,required。對應(yīng)的UILayoutPriority的分別是UILayoutPriorityFittingSizeLevel,UILayoutPriorityDefaultLow,UILayoutPriorityDefaultHigh,UILayoutPriorityRequired。
-
minWidth:對應(yīng)NSLayoutRelationGreaterThanOrEqual,設(shè)置一個(gè)最小的寬
-
maxWidth:對應(yīng)NSLayoutRelationLessThanOrEqual,設(shè)置一個(gè)最大的寬
?
PartView視圖控件相關(guān)設(shè)置
?
通過以下屬性即可生成對應(yīng)的UILabel,UIImageView或者UIButton等控件視圖,而不用特別指出需要生成哪種控件視圖
?
-
text:設(shè)置文字內(nèi)容
-
font:設(shè)置字體,可以帶入一個(gè)UIFont,也可以直接設(shè)置一個(gè)字體大小,解析時(shí)會判斷類型。
-
color:設(shè)置顏色,可以帶入一個(gè)UIColor,也可以直接設(shè)置一個(gè)十六進(jìn)制顏色,解析時(shí)會判斷類型。
-
imageName:設(shè)置本地圖片,值是本地圖片名稱。
-
image:帶入一個(gè)UIImage。
-
imageUrl:設(shè)置一個(gè)網(wǎng)絡(luò)圖片的url地址,ps:目前需要通過來帶入一個(gè)字符串。
?
PartView的通用設(shè)置
?
可以為PartView創(chuàng)建一個(gè)底部視圖,并設(shè)置其樣式。也可以添加一個(gè)UIButton設(shè)置UIControlStateHighlighted時(shí)的樣式。
?
-
backColor:設(shè)置底部視圖的顏色,可以帶入一個(gè)UIColor,也可以直接設(shè)置一個(gè)十六進(jìn)制顏色,解析時(shí)會判斷類型。
-
backPaddingHorizontal:設(shè)置當(dāng)前PartView視圖距離底部視圖top和bottom的間距。
-
backPaddingVertical:設(shè)置當(dāng)前PartView視圖距離底部視圖left和right的間距。
-
backBorderColor:設(shè)置底部視圖邊框的顏色,可以帶入一個(gè)UIColor,也可以直接設(shè)置一個(gè)十六進(jìn)制顏色,解析時(shí)會判斷類型。
-
backBorderWidth:設(shè)置底部視圖邊框?qū)挕?/p>
-
radius:設(shè)置底部視圖的圓角半徑。
-
button:帶入一個(gè)button。
-
buttonHighlightColor:設(shè)置button在UIControlStateHighlighted時(shí)的顏色,默認(rèn)是透明度0.05的黑色。
?
解析格式化語言
?
解析過程的第一步采用掃描scanner程序?qū)⒆址凑辗治龇柋韺⒆址餍蛄惺占接幸饬x的單元中。
?
第二步將這些單元逐個(gè)歸類到對應(yīng)的類別中。比如解析到“()”里內(nèi)容時(shí)就將其歸類到對應(yīng)的AssembleView的屬性或者PartView的屬性類別中。在歸類過程中會出現(xiàn)PartView是AssembleView,這個(gè)Assemble里面又有這樣作為PartView的AssembleView這樣層層套的情況,所以需要采用類似引用計(jì)數(shù)方式保證在最后一個(gè)“}”符號結(jié)束時(shí)能將整個(gè)Assemble遞歸進(jìn)行解析。
?
第三步將各個(gè)類別集合轉(zhuǎn)換成對應(yīng)原生代碼從而生成對應(yīng)的視圖布局。
?
具體實(shí)現(xiàn)可以查看STMAssembleView.m文件。Github地址:https://github.com/ming1016/STMAssembleView
?
如何生成頁面
?
生成頁面需要實(shí)現(xiàn)格式化語言對應(yīng)的原生代碼,所有PartView的屬性都會存放在STMPartMaker里,包括帶入的自定義視圖還有用于生成視圖控件的屬性等。PartView屬性設(shè)置完成后會在STMPartView這個(gè)類中先決定對應(yīng)的視圖控件,并將STMPartMaker里的屬性都設(shè)置上。實(shí)現(xiàn)代碼可以查看STMPartView.m里的- (STMPartView *)buildPartView方法。
?
接下來STMAssembleView會在buildAssembleView時(shí)進(jìn)行布局,具體實(shí)現(xiàn)代碼可以查看STMAssembleView.m里的- (STMAssembleView *)buildAssembleView方法。
?
總結(jié)
以上是生活随笔為你收集整理的制作一个类似苹果VFL的格式化语言来描述UIStackView的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【CodeForces 577C】Vas
- 下一篇: LateUpdate、Late、Fixe