早在前兩年還沒有iPhone6(s)、iPhone6(s) plus出現(xiàn)的時候,在開發(fā)iOS的應用程序的時候感覺在布局上都完爆Android,因為雖然iPhone5與iPhone4的高度不一樣,但是參照寬度(320px)都是一樣的。
??但是在iPhone6(s)、iPhone6(s) plus出現(xiàn)后,iPhone的屏幕分辨率開始碎片化,但是使用iOS的AutoLayout好像也是屌屌的,完全能夠針對屏幕大小進行相應的自動布局(相對布局)。
??但是眼尖的程序員可能會發(fā)現(xiàn):在iPhone5上的控件如果設置了邊距,字體大小等等,在iPhone6Plus上也是一樣一樣的,并沒有像Android上會按照屏幕的分辨率比例縮放。這是因為在Android開發(fā)過程中并沒有使用像素單位px,而是使用的pd為單位,而字體使用的sp為單位。

這是iPhone6p與iPhone6的對比圖,幾乎肉眼可見(本人用測量工具側量過),加入按鈕高度是一樣的。
其實這樣的布局也不會帶來什么特別的困擾,只要設計師考慮了iOS布局的這個特性,設計得當,最后出來的效果無非是iPhone6p出來的效果空一些,而iPhone5出來的效果經(jīng)湊一些。
??一直以來我也是按照這種設計模式開發(fā)自己的App。
然而命運出現(xiàn)了轉折......
??在新的一個項目中,設計師設計的圖紙是在1242px的畫布(參考的iPhone6p的尺寸)上設計的。按照iPhone6p的屏幕尺寸切圖額和標注給我后,導致出來的結果是在iPhone6p上效果上佳,但是在iPhone5上就開始擠在一起,甚至出現(xiàn)了有些控件疊加在一起。
??這就是因為iOS開發(fā)布局后字體大小、間距、控件大小并不會按照屏幕的分辨率等比例縮放的結果。
??然后設計師又重新按照iPhone6的尺寸標注了一份新的設計圖后,開發(fā)出來的結果也是并不理想,因為在iPhone6上表現(xiàn)上佳,但是iPhone5上緊了,在iPhone6p上又顯得比較空了。

問題所在:
最后我發(fā)現(xiàn),大部分設計師在設計的時候,工作流程都是這樣:
1.在自己的參照的屏幕尺寸下設計;
2.導出設計圖,放在iPhone6p、iPhone6、iPhone5等設備上查看效果;
3.效果感覺滿意后就可以開始標注、切圖了;
看著好像并沒有什么問題,但是問題恰恰就出現(xiàn)在第2步,導出圖片放在手機中查看,如果寬度和手機屏幕寬度一致,高度按比例縮放了,那么其實圖片里面展示的字體大小、控件間距、控件大小都隨著該比例縮放了。但是iOS開發(fā)中并沒有進行縮放的操作,這也就成為了為什么設計師明明看著好好的,可是出來的效果怎么就出現(xiàn)偏差了呢?
最后設計師問我,能不能按照屏幕分辨率直接等比例縮放,這樣在所有的屏幕上就全部都完美了。

參照上圖的意思是說,在iPhone6p上這個itemView能夠展示2.5個,那么在iPhone6上面也是2.5個,而不會因為iPhone6的屏幕寬度小了就只展示2個。
說了這么多,也應該開始正真的代碼開發(fā)了。
先放兩張效果圖看看:


效果顯示不管是字體大小、控件間距、控件大小都跟隨屏幕大小自適應縮放大小,然后終于合了設計師的心意了~
我給我的這個操作起了個名字:比例自動布局(AutoLayout)。使用的AutoLayout第三方庫是PureLayout,這里就不再對PureLayout做過多的介紹了,不知道的同學可以在github上搜索下載學習。
??大部分操作也是在PureLayout的源文件里進行修改操作。
1.選取參考尺寸
因為自己是從iPhone4、iPhone5開發(fā)過來的,原來的很多設計圖,都是參考這個尺寸做的,所以我選擇的參考尺寸是320px,當然你也可以選擇其他的參考尺寸,比如iPhone6的375px。
在UIView擴展類:ALView+PureLayout.m中添加:
//依據(jù)iPhone5的尺寸得到當前屏幕相對于iPhone5屏幕尺寸的大小
+(CGFloat)sizeFromIphone5:(CGFloat)size{
#if TARGET_OS_IPHONE
static float width = 0;
if (width == 0) {
width = [UIScreen mainScreen].bounds.size.width;
}
return width/320.0*size;
#endif
return size;
}
//依據(jù)真實的尺寸得到iPhone5屏幕尺寸的大小
+(CGFloat)sizeFromRealSize:(CGFloat)size{
#if TARGET_OS_IPHONE
static float width = 0;
if (width == 0) {
width = [UIScreen mainScreen].bounds.size.width;
}
return 320.0/width*size;
#endif
return size;
}
2.字體大小修改
對UIFont擴展方法:
#import "UIFont+XM.h"
@implementation UIFont (CW)
+(UIFont *)cwFontWithSize:(CGFloat)fontSize{
return [UIFont systemFontOfSize:[UIView sizeFromIphone5:fontSize]];
}
+(UIFont *)cwBoldFontWithSize:(CGFloat)fontSize{
return [UIFont boldSystemFontOfSize:[UIView sizeFromIphone5:fontSize]];
}
@end
在開發(fā)中全部字體設置都用這個方法來執(zhí)行。
3.控件大小
在傳入size后,對size進行加工:
size = [UIView sizeFromIphone5:size];
- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size relation:(NSLayoutRelation)relation
{
size = [UIView sizeFromIphone5:size];
self.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutAttribute layoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)dimension];
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:layoutAttribute relatedBy:relation toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:size];
[constraint autoInstall];
return constraint;
}
4.控件間距
在傳入offset后,對offset進行加工:
offset = [UIView sizeFromIphone5:offset];
因為不管是兩個控件之間的相對間距,還是相對于父控件的間距,在PureLayout中最后執(zhí)行都是這個方法:
- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation
{
offset = [UIView sizeFromIphone5:offset];
self.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutAttribute layoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:attribute];
NSLayoutAttribute toLayoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:toAttribute];
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:layoutAttribute relatedBy:relation toItem:otherView attribute:toLayoutAttribute multiplier:1.0 constant:offset];
[constraint autoInstall];
return constraint;
}
5.對抗系統(tǒng)自帶大小
iOS有很多自帶的布局控件,而且大?。ㄌ貏e是高度)是固定的,我的操作是:
1.UINavigationBar:全部隱藏,就當沒有這個控件,全部自定義;
2.UITabBar:因為并沒有什么影響,所以不予置理;
6.心理
為什么會把這個單獨提出來,原因是開發(fā)中需要調(diào)整自己的心理影響,現(xiàn)在的做法是目前的屏幕寬度都是320px。
比如在設置UILabel的preferredMaxLayoutWidth屬性的時候:
-(void)layoutSubviews{
[super layoutSubviews];
contentLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.frame)-[UIView sizeFromIphone5:10]-[UIView sizeFromIphone5:26];
commentLabel.preferredMaxLayoutWidth = CGRectGetWidth(commentView.frame)-[UIView sizeFromIphone5:22];
}
比如在得到屏幕5等分寬度的時候:
float width = 320/5;
7.總結
設計師工作流程就變成了這樣:
1.在自己的參照的屏幕尺寸下設計;
2.導出設計圖,放在iPhone6p、iPhone6、iPhone5等設備上查看效果;
3.效果感覺滿意后就可以開始在【960px或者640px或者320px上進行標注】,因為可能直接在320px上標注像素會丟失,最好在960px上標注,開發(fā)人員自行除以3處理;
4.1242px上切圖,因為要保證圖片的分辨率在大屏手機上的清晰度;
可能還有很多沒有考慮到(涉世未深,工作經(jīng)驗并不多),這里提出的只是一個參考的思路,本人對PureLayout的使用也是剛剛接觸,其中的方法,我常用的也就這么幾個,如果用到了其他的方法,肯定是要注意的。