Autolayout,開始于iOS6.0
一.什么時候用autolayout比較適合
1.不負(fù)責(zé)任的騎墻派說法:apple的設(shè)備越來越多了,你的應(yīng)用應(yīng)該都使用al。(并且用sb)
2.要看應(yīng)用內(nèi)容決定。如果你的內(nèi)容是信息眾多,同時需要展示的類別也很多,尺寸動態(tài)不定,甚至這些是在列表中的。(如社交應(yīng)用)。Al能給于很大的幫助。
3.Mac os的應(yīng)用?,F(xiàn)在都做iOS了。mac app的窗口,會有大小變化。al比較合適。
4.支持多向轉(zhuǎn)屏的iPad應(yīng)用。(有需要支持多方向iphone場景么?那么長,腦殘了?)
5.其他業(yè)務(wù)不復(fù)雜,頁面較少的應(yīng)用,其實,cocoa程序員寫了多年code都有自己的ui編程習(xí)慣,這些習(xí)慣對于他們來說是很高效的。就算是第一項所說,布局的坐標(biāo)都是相對的。
如果是習(xí)慣于code寫布局的,建議可以繼續(xù)沿用,同時也要學(xué)習(xí)al。自我感覺al和傳統(tǒng)布局寫法,工作量不會相差太多。但是VFL用熟練了以后會有很大的改善。
二.autolayout的基礎(chǔ)理論
al的核心出發(fā)點是
1.view具有自我計算尺寸,布局的能力。通過它自身的內(nèi)容,能夠得到尺寸。
2.view的布局位置,確定于它與superview及其他view的關(guān)系。
3.與傳統(tǒng)的autoresizingmask自適應(yīng)相比,al更精確,能絕對的確定view的布局。
4.view不一定需要一個初始的rect。al中,view如果有足夠的constraint,便可以確定自己的尺寸和位置,并且知道自己和其他view的關(guān)系。即,想確定view的布局,就給它(們)添加constraint。
三.xib下的autolayout
似乎al和xib布局模式生來就是要搞在一起的。用xib加al,view布局非常簡單容易。編程工作立刻變成了美工的連線拼圖游戲。
開啟xib或者sb后,選擇需要view(s)。選擇menu的Editor,選擇Pin。子菜單的項目就是可用的constraints。
Width:固定自身寬度
Height:。。。
H- Spacing: 固定兩個view的水平間距
V- Spacing:。。。
下面4個分別是view相對于superview的左、右、上、下的間距
Widths Equally:兩個view保持寬度相同
Heights Equally:。。。
xib界面右下角工具條也有可以編輯constraint的方式:
每個constraint添加后都是可以編輯的。選中某個constraint后開啟右邊欄選inspector??梢孕薷臄?shù)值。(這個數(shù)值是view間的偏移量)和優(yōu)先級。
自己慢慢拖著玩去。這不是傻瓜教程。點到位,自己研究。
xib下的al比較直觀??梢曰究吹叫Ч驼`差值。還有不正確的constraint的提示。少了constraint編譯器會補(bǔ),多了會提示報錯。(不過都會引起界面布局不對,自己慢慢調(diào)吧,哥現(xiàn)在還是滿篇alert,沒有讓編譯器感覺矛盾費解的constraint,都是可以work的。)
還有resolve的方式解決constraint的問題,抱歉,我不會。
四.編碼方式使用autolayout
對于頁面不多,的普通應(yīng)用。xib/sb加al。拖拖拽拽。娛樂中就可以完成UI的工作。al的確給于了不少方便。
不過多年的強(qiáng)迫癥程序猿怎么會忍受這種很遜的方式。(拖積木?不敲代碼?好像一天沒做事。)
1.Visual format language?。☉?yīng)該不算語言)
Apple的工程師很有愛,發(fā)明了這種哭笑不得的象形文字。感覺它就是種解析方式。
Apple的官方文檔給出了少之又少的文檔和坑爹的例子。(視頻我沒看,不知道怎么樣)網(wǎng)上的同學(xué)們也寫了點不痛不癢的幾句代碼。你這是學(xué)了1+1就讓人搞微積分的節(jié)奏么?要寫不寫清楚,不如不寫。
從厚道的老外那看了幾篇。自己體會了些,分享給大家。只是個基本水平吧,會了這些,代碼寫al應(yīng)該沒有問題了。深入的我也還不會,希望遇到更有愛的牛人分享。
VFL在程序中由支持:
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
- 它返回一組constraint.
- format是你的VFL字串,等下講。
- opts自己點去頭文件看。有些情況會用,等下有例子。
- metrics是一個奇妙的字典,是你自己定義的。這個字典里面的key可以寫在format字串中。編譯器解析時,自動替換為metrics字典中的value。等下有例子。
- views是需要constraint關(guān)系的所有view.(也可以是一個)
2.VFL例子
寫vfl字串的時候,腦海里要想象出畫面的合理性。不合理的constraint會導(dǎo)致程序運行時報錯或者直接崩潰。
隨便寫幾個
NSDictionary *dict1 = NSDictionaryOfVariableBindings(_boxV,_headerL,_imageV,_backBtn,_doneBtn);
NSDictionary *metrics = @{@"hPadding":@5,@"vPadding":@5,@"imageEdge":@150.0};
NSString *vfl = @"|-hPadding-[_boxV]-hPadding-|";
NSString *vfl0 = @"V:|-25-[_boxV]";
NSString *vfl3 = @"V:|-vPadding-[_headerL]-vPadding-[_imageV(imageEdge)]-vPadding-[_backBtn]-vPadding-|";
dict1就是api 中需要的最后一個參數(shù)views。由上述宏來完成。
metrics定義了一些vfl中要用的參數(shù)。
下面有些vfl字串,一看便知如何使用metrics。
看到:
1)"|"表示superview.
|-間距-[view1對象名]-(>=20)-[view2對象名]
不寫H/V就表示橫向,間距可以寫固定值也可寫>/<。
形象化的理解,"|"是用來確定view上、下、左、右關(guān)系的。
想要確定從上到下的關(guān)系,就加V:|。那么這個vfl字串就可以描述從上到下的view們的關(guān)系。
2)看到vfl3里面,方括號表示view,圓括號表示尺寸數(shù)值。支持大小等于?;蛘吡硪粋€view |-[view1(view2)],v1的寬度等于v2。
3)優(yōu)先級用@表示。如V:|-50@750-[view(55)],或者寫到metrics里面更好。
具體定義查看UILayoutPriority。有幾個固定的數(shù)值。1000表示必須支持。
4)options,這個要看具體需要。如果是豎排V布局,可以添加NSLayoutFormatAlignAllLeft,讓他們對齊。
根據(jù)需要也可以添加按位或NSLayoutFormatAlignAllLeft | NSLayoutFormatAlignAllRight。(鬼知道什么需要,自己看經(jīng)驗吧)
5)寫好以后一般把constraint添加給superview:
NSString *vfl1 = @"|-hPadding-[_headerL]-hPadding-|";
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl1 options:0 metrics:metrics views:dict1]];
6)還有一個api用于生成單個constaint
+(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
對于參數(shù),記得,view1.attr1 = view2.attr2 * multiplier + constant就好。
這個是不用VFL的,好理解,但是不方便。如果用這個寫。工作兩不會比傳統(tǒng)布局少多少。
五.實際操作中的問題
上面都是理論,世界操作會有些奇怪的問題要注意。這節(jié)才是重點。
xib模式,沒啥要注意的,xib里報warning就報吧,我也不知道怎么弄,一切正常就好。
編碼模式中,
1.addConstraint(s)前,view應(yīng)該去部被addSubView上去了。
2.不必給views寫frame
3.給必要的view關(guān)掉AutoresizeingMask。[_aView setTranslatesAutoresizingMaskIntoConstraints:NO];
4.UILabel換行要寫linebreakMode,要寫numberOfLines(iOS7.0默認(rèn)好像是1,坑爹了)
5.UILabel要想換行,一定要添加preferredMaxLayoutWidth。否則沒法初始化寬度。
編碼模式感受到的最大方便。label換行不用寫行高計算了。完全自動適應(yīng)。label所在的superview也會自動計算rect。這才是al的精華。
所以,可以不用寫這些了:
[objc] view plaincopy
/*
if([[UIDevice currentDevice].systemVersion floatValue]<7.0){
CGSize titleS = [title sizeWithFont:[_headerL font]
constrainedToSize:CGSizeMake(270.0, CGFLOAT_MAX)
lineBreakMode:NSLineBreakByWordWrapping];
_headerL.frame = CGRectMake(_headerL.frame.origin.x, _headerL.frame.origin.y,
_headerL.frame.size.width, titleS.height);
}else{
CGRect titleR = [title boundingRectWithSize:CGSizeMake(270.0, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:nil
context:nil];
headerL.frame = CGRectMake(_headerL.frame.origin.x, _headerL.frame.origin.y,
_headerL.frame.size.width, titleR.size.height);
}
*/
我遇到了些問題,至今沒有解決:
純代碼寫的Viewcontroller 無法正常顯示al布局。用空白的xib做了vc后,其余再用code寫,就正常了。懷疑自己寫的self.view,還需要針對autolayout做什么處理。至此,al,基本功能已經(jīng)可以為你服務(wù)了。的確方便很多,建議還是使用VFL代碼模式,熟練后能夠提高很多效率。