【iOS】利用PureLayout实现:比例自动布局(AutoLayout)

早在前两年还没有iPhone6(s)、iPhone6(s) plus出现的时候,在开发iOS的应用程序的时候感觉在布局上都完爆Android,因为虽然iPhone5与iPhone4的高度不一样,但是参照宽度(320px)都是一样的。
  但是在iPhone6(s)、iPhone6(s) plus出现后,iPhone的屏幕分辨率开始碎片化,但是使用iOS的AutoLayout好像也是屌屌的,完全能够针对屏幕大小进行相应的自动布局(相对布局)。
  但是眼尖的程序员可能会发现:在iPhone5上的控件如果设置了边距,字体大小等等,在iPhone6Plus上也是一样一样的,并没有像Android上会按照屏幕的分辨率比例缩放。这是因为在Android开发过程中并没有使用像素单位px,而是使用的pd为单位,而字体使用的sp为单位。

对比图.png

这是iPhone6p与iPhone6的对比图,几乎肉眼可见(本人用测量工具侧量过),加入按钮高度是一样的。

其实这样的布局也不会带来什么特别的困扰,只要设计师考虑了iOS布局的这个特性,设计得当,最后出来的效果无非是iPhone6p出来的效果空一些,而iPhone5出来的效果经凑一些。
  一直以来我也是按照这种设计模式开发自己的App。


然而命运出现了转折......
  在新的一个项目中,设计师设计的图纸是在1242px的画布(参考的iPhone6p的尺寸)上设计的。按照iPhone6p的屏幕尺寸切图额和标注给我后,导致出来的结果是在iPhone6p上效果上佳,但是在iPhone5上就开始挤在一起,甚至出现了有些控件叠加在一起。
  这就是因为iOS开发布局后字体大小、间距、控件大小并不会按照屏幕的分辨率等比例缩放的结果。
  然后设计师又重新按照iPhone6的尺寸标注了一份新的设计图后,开发出来的结果也是并不理想,因为在iPhone6上表现上佳,但是iPhone5上紧了,在iPhone6p上又显得比较空了。

对比图2.png
问题所在:

最后我发现,大部分设计师在设计的时候,工作流程都是这样:
1.在自己的参照的屏幕尺寸下设计;
2.导出设计图,放在iPhone6p、iPhone6、iPhone5等设备上查看效果;
3.效果感觉满意后就可以开始标注、切图了;

看着好像并没有什么问题,但是问题恰恰就出现在第2步,导出图片放在手机中查看,如果宽度和手机屏幕宽度一致,高度按比例缩放了,那么其实图片里面展示的字体大小、控件间距、控件大小都随着该比例缩放了。但是iOS开发中并没有进行缩放的操作,这也就成为了为什么设计师明明看着好好的,可是出来的效果怎么就出现偏差了呢?

最后设计师问我,能不能按照屏幕分辨率直接等比例缩放,这样在所有的屏幕上就全部都完美了。

对比图3.png

参照上图的意思是说,在iPhone6p上这个itemView能够展示2.5个,那么在iPhone6上面也是2.5个,而不会因为iPhone6的屏幕宽度小了就只展示2个。


说了这么多,也应该开始正真的代码开发了。

先放两张效果图看看:

对比图4.png
对比图5.png

效果显示不管是字体大小、控件间距、控件大小都跟随屏幕大小自适应缩放大小,然后终于合了设计师的心意了~

我给我的这个操作起了个名字:比例自动布局(AutoLayout)。使用的AutoLayout第三方库是PureLayout,这里就不再对PureLayout做过多的介绍了,不知道的同学可以在github上搜索下载学习。
  大部分操作也是在PureLayout的源文件里进行修改操作。

1.选取参考尺寸

因为自己是从iPhone4、iPhone5开发过来的,原来的很多设计图,都是参考这个尺寸做的,所以我选择的参考尺寸是320px,当然你也可以选择其他的参考尺寸,比如iPhone6的375px。

在UIView扩展类:ALView+PureLayout.m中添加:

//依据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;
}

//依据真实的尺寸得到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

在开发中全部字体设置都用这个方法来执行。

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中最后执行都是这个方法:

- (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.对抗系统自带大小

iOS有很多自带的布局控件,而且大小(特别是高度)是固定的,我的操作是:

1.UINavigationBar:全部隐藏,就当没有这个控件,全部自定义;
2.UITabBar:因为并没有什么影响,所以不予置理;

6.心理

为什么会把这个单独提出来,原因是开发中需要调整自己的心理影响,现在的做法是目前的屏幕宽度都是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上标注,开发人员自行除以3处理;
4.1242px上切图,因为要保证图片的分辨率在大屏手机上的清晰度;

可能还有很多没有考虑到(涉世未深,工作经验并不多),这里提出的只是一个参考的思路,本人对PureLayout的使用也是刚刚接触,其中的方法,我常用的也就这么几个,如果用到了其他的方法,肯定是要注意的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容