之前的寫 ATStackView 1.0 版本由于是繼承UIStackView的琢唾,考慮該組件的缺陷而引發(fā)的一些性能上、實(shí)用性贩疙、可擴(kuò)展性上的問(wèn)題诀诊,決定對(duì)該組件進(jìn)行底部重構(gòu)盆顾。升級(jí)2.0擺脫了UIStackView的包袱,同時(shí)不再使用約束進(jìn)行布局畏梆。優(yōu)化布局算法等操作您宪。
ATStackView 1.0缺陷:
UIStackView是iOS9.0推出的奈懒,這將意味著無(wú)法支持更低版本的iOS系統(tǒng)。
ATStackView 1.0 和 UIStackView都是基于自動(dòng)布局的宪巨,頻繁地使用它們會(huì)產(chǎn)生大量約束代碼磷杏,而約束代碼最終通過(guò)線性方程求解得出frame值,雖然蘋果公司在iOS12對(duì)自動(dòng)布局算法進(jìn)行了優(yōu)化捏卓,但是還是不能解決低版本的iOS系統(tǒng)下約束性能的問(wèn)題极祸。
繼承UIStackView雖然帶來(lái)了一些布局上的便利,但是它的可擴(kuò)展性很低怠晴,并且由于它的源碼是未知的遥金,使得添加新特性比較困難。比如說(shuō)蒜田,ATStackView 1.0 有個(gè)方法可以將元素從尾部開(kāi)始添加稿械,這個(gè)過(guò)程的實(shí)現(xiàn)實(shí)際上是通過(guò)添加一個(gè)約束優(yōu)先級(jí)比較低的自伸長(zhǎng)view,將頭部和尾部連接(撐)起來(lái)冲粤,由于它的高度是0美莫,所以用戶感覺(jué)不到它。這個(gè)功能看似很酷梯捕,但是本來(lái)只要添加兩個(gè)view的操作厢呵,結(jié)果添加了三個(gè)view。萬(wàn)一開(kāi)發(fā)者需要調(diào)用subviews進(jìn)行操作傀顾,那后果豈不是不堪設(shè)想...襟铭。
基于這些問(wèn)題的存在,決定重構(gòu)ATStackView短曾,ATStackView 2.0將繼承NSObject蝌矛,進(jìn)行輕量級(jí)改造。
github鏈接: https://github.com/AutoJiang/ATStackView
ATStackView 2.0的使用介紹:
1. 導(dǎo)入頭文件
#import "UIView+ATStack.h"
2. 快速創(chuàng)建一個(gè)橫向布局或者縱向布局的棧(ATVerStack或 ATHorStack)错英。
ATVerStack *stack = [self.view getStackVer];
創(chuàng)建一個(gè)和 self.view 等大,縱向排列的棧隆豹。
/**快速創(chuàng)建一個(gè)垂直方向椭岩、子控件從上到下布局的棧*/
-(ATVerStack *)getStackVer;
/**快速創(chuàng)建一個(gè)水平方向、子控件從左到右布局的棧*/
-(ATHorStack *)getStackHor;
/**快速創(chuàng)建一個(gè)水平方向璃赡、子控件均分的棧*/
-(ATHorStack *)getStackHorEqual;
/**快速創(chuàng)建一個(gè)垂直方向判哥、子控件均分的棧*/
-(ATVerStack *)getStackVerEqual;
當(dāng)然,如果我們不想stack和view一樣大碉考,我們可以調(diào)用以下方法:
//inset代表內(nèi)間距
-(ATVerStack *)getStackVerWithInset:(UIEdgeInsets)inset;
-(ATHorStack *)getStackHorWithInset:(UIEdgeInsets)inset;
-(ATHorStack *)getStackHorEqualWithInset:(UIEdgeInsets)inset;
-(ATVerStack *)getStackVerEqualWithInset:(UIEdgeInsets)inset;
通過(guò)設(shè)置inset來(lái)控制stack和view的間距塌计。(注:這里的stack并不像V1.0那樣是一個(gè)UIStackView實(shí)體,它實(shí)際上只是一個(gè)虛擬的 frame侯谁,所以它并沒(méi)有在view上面添加這個(gè)stack)
通過(guò)調(diào)用view分類的方法生成一個(gè)stack锌仅,
接下來(lái)章钾,我們往這個(gè)stack里面添加元素即可。
3. 添加元素(添加控件热芹,或者其他棧)
這種方式直接添加view贱傀,view內(nèi)部必須有高度上面的約束。
[stack addArrangedSubview:view];
推薦使用以下方式:(height 代表的約束height = 30 , isFill = true代表寬度和stack一樣寬伊脓,isFill = false代表控件使用自適應(yīng)的寬)
UIView *view = [UIView new];
[stack addArrangedSubview:view height:30 isFill:true];
4. 添加spacing
默認(rèn)的ATStackView的spacing是0府寒,一旦設(shè)置了stack.spacing = 10之后,棧內(nèi)所有元素之間的間距都是10报腔。
ATVerStackView *stack = [ATVerStackView getStackVer];
stack.spacing = 10;
當(dāng)然你還可以添加額外的間距株搔。以下代碼代表下一個(gè)元素和上一個(gè)元素之間的間距為30。如果你同時(shí)設(shè)置了stack.spacing = 10纯蛾,那么它們的間距就是40纤房。
[stack addSpacing:30];
如果你不想從頭部插入元素,而是想從其他位置插入時(shí)茅撞,你可以調(diào)用以下方法:
-(void)addArrangedSubview:(UIView*)view height:(CGFloat)height isFill:(BOOL)isFill position:(ATStackViewPosition)position;
typedef enum ATStackViewPosition: NSUInteger {
/**從頭部添加元素*/
ATStackViewPositionHead = 0,
/**從中間添加元素*/
ATStackViewPositionCenter,
/**從尾部添加元素*/
ATStackViewPositionTail,
} ATStackViewPosition;
ATSackView支持從頭部帆卓,中間,或尾部添加元素米丘。
通過(guò)設(shè)置 position = ATStackViewPositionTail 屬性剑令,可以將元素添加至頭部,或者尾部(默認(rèn)是添加至頭部)拄查。
想要ATStackView能從底部或中間添加元素必須得滿足以下1個(gè)條件:
- 父視圖不是UIScrollView類型吁津。
因?yàn)閁IScrollView內(nèi)部是無(wú)限大的,ATStackView并不知道它的底部在哪兒堕扶。如果一定要用碍脏,布局
會(huì)當(dāng)作內(nèi)部大小和UIScrollView的frame一致計(jì)算。
5. 調(diào)用布局方法
[stack layoutFrame];
在添加完元素以后稍算,只有調(diào)用了layoutFrame方法典尾,才能對(duì)內(nèi)部元素開(kāi)始進(jìn)行布局。當(dāng)內(nèi)部有多層嵌套棧的時(shí)候糊探,只需要調(diào)用最外層的layoutFrame方法即可钾埂,布局算法會(huì)遍歷所有元素去執(zhí)行l(wèi)ayoutFrame。
實(shí)戰(zhàn):
微信-發(fā)現(xiàn)
50多行代碼輕松實(shí)現(xiàn)“微信-發(fā)現(xiàn)”頁(yè)面的簡(jiǎn)單布局科平。
運(yùn)行結(jié)果:
九宮格:
運(yùn)行結(jié)果:
(UIView+ATStack.h)擴(kuò)展方法和屬性介紹:
//添加分割線
-(UIView *)addLineSeparate;
//返回的分割線可自定義顏色和高度
-(UIView *)addLineSeparateWithLelfPadding:(CGFloat)leftPadding;
//隱藏元素褥紫,同時(shí)改變其他元素的位置
-(void)setAt_hidden:(BOOL)hidden;
-(BOOL)at_hidden;
-(void)setAt_width:(CGFloat)width;
-(CGFloat)at_width;
-(void)setAt_height:(CGFloat)height;
-(CGFloat)at_height;
熟悉UIStackView的人肯定知道,子控件設(shè)置hidden = true的時(shí)候瞪慧,這個(gè)控件不僅會(huì)隱藏髓考,后面的元素位置也會(huì)自動(dòng)向前移動(dòng)。這里的at_hidden屬性就是這樣的作用弃酌。
demo演示:
希望這一套布局方案能為大家的開(kāi)發(fā)帶來(lái)便利氨菇!??