【iOS】利用PureLayout實現(xiàn):比例自動布局(AutoLayout)

早在前兩年還沒有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為單位。

對比圖.png

這是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上又顯得比較空了。

對比圖2.png
問題所在:

最后我發(fā)現(xiàn),大部分設計師在設計的時候,工作流程都是這樣:
1.在自己的參照的屏幕尺寸下設計;
2.導出設計圖,放在iPhone6p、iPhone6、iPhone5等設備上查看效果;
3.效果感覺滿意后就可以開始標注、切圖了;

看著好像并沒有什么問題,但是問題恰恰就出現(xiàn)在第2步,導出圖片放在手機中查看,如果寬度和手機屏幕寬度一致,高度按比例縮放了,那么其實圖片里面展示的字體大小、控件間距、控件大小都隨著該比例縮放了。但是iOS開發(fā)中并沒有進行縮放的操作,這也就成為了為什么設計師明明看著好好的,可是出來的效果怎么就出現(xiàn)偏差了呢?

最后設計師問我,能不能按照屏幕分辨率直接等比例縮放,這樣在所有的屏幕上就全部都完美了。

對比圖3.png

參照上圖的意思是說,在iPhone6p上這個itemView能夠展示2.5個,那么在iPhone6上面也是2.5個,而不會因為iPhone6的屏幕寬度小了就只展示2個。


說了這么多,也應該開始正真的代碼開發(fā)了。

先放兩張效果圖看看:

對比圖4.png
對比圖5.png

效果顯示不管是字體大小、控件間距、控件大小都跟隨屏幕大小自適應縮放大小,然后終于合了設計師的心意了~

我給我的這個操作起了個名字:比例自動布局(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的使用也是剛剛接觸,其中的方法,我常用的也就這么幾個,如果用到了其他的方法,肯定是要注意的。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容