一直以来,我都是一个代码流,喜欢用纯代码去构建app,并觉得这是一件很酷的事情。当iPhone 5出来了,我还觉得没什么问题,但是当iPhone 6和iPhone 6 plus都出来,屏幕的分辨率一下子就多起来了,如果加上iPad以及还没上架的apple watch,iPhone的分辨率也各种各样了。
当分辨率变得各种各样的时候,开发者就再也不能用480,320这种数字了,这种数字做过iOS开发的人都懂,也几乎每个人都用过。但是,现在你还对这类数字十分不舍的话,那就只能在你的代码里面写上各种if else了,这种if else的布局显然不是解决问题的好方法,所以苹果就推出了autolayout这种神器。
一、关于自动布局(Autolayout)
自动布局,听起来各种高大上,它是跟着iOS 6一起出来的,那时候主流的app还支持到iOS 4.0(甚至到现在还有各种app支持到iOS 4.3),所以这种技术一直没人去了解,
没人去使用,再加上苹果关于AutoLayout 的API也没有很好的封装,反正我是看着没什么喜欢用的欲望的了。
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format
options:(NSLayoutFormatOptions)opts
metrics:(NSDictionary *)metrics
views:(NSDictionary *)views;
后面万能的开源界出了一个Masonry(https://github.com/Masonry/Masonry)
这个库对于AutoLayout进行了很好的封装,这个也是我对于AutoLayout的一次比较深入的了解。
Masonry在github的主页就有很好的介绍了,这里就不铺开说了。
通过Masonry,可以了解到,AutoLayout是为了在一个在不确定的情况下可以得到一个比较确定的定位。
比如在View3里面有View1和View2,那么怎么确保1,2的大小是一样的,而且它们之间水平间隔是10
它们跟view3的左右上下间隔也是10。
在iPhone 4下面的话大家估计会这么写:
view1.frame = CGRectMake(10,10,(320-30)/2.0,480-20);
view2.frame = CGRectMake(CGRectGetMaxX(view1.frame)+10,10,(320-30)/2.0,480-20);
那么在iPhone 5呢,就把480换成568.
那么在iPhone 6呢,就把320换成375,把480换成667
那么在iPhone 6 plus呢,就把320换成414,把480换成736.
假如算上横屏和iPad的分辨率,iOS开发者估计要哭晕在厕所里面了。
二、自动布局如何使用
苹果出了iPhone 5之后,也预感到自己会有各种各样的分辨率了
其实mac里面就有各种各样的分辨率了,mac开发也早就有自动布局的东西,
只是在iPhone 里面不知道是不是乔帮主那个经典比例尺寸导致,在iOS开发中一直都限定在320*480这个框框里面。
回到刚刚的问题里面,如果需要适应所有的分辨率,用自动布局该怎么做。
首先打开一个xib,这里面我随便新建了一个。
然后把这个xib中把Use Auto Layout勾选了(在高版本的Xcode里面这个是默认勾选的)
我使用的是Xcode 6.1,在xib选项设置那里Simulated Metrics里面有个size,选择freedom
然后这时候你就发现那个view是可以随意放大缩小的。
我们在里面随意拖动2个view进去,为了比较显眼,我把颜色配好。
那么我们这次的要求是,左右2个色块的大小是一致的就是等宽高,2个色块跟父View的距离为5,
2个色块中间的距离也是5.
为了比较好区分,我把左边的色块命名为view1,右边的为view2.
首先,选中view1和view2(按住command就可以选取了),
选中之后,在Xcode的菜单栏选择Editor->Pin
选择Widths Equally,同样的操作选择Heights Equally。
对于Pin里面的操作,我大致说一下吧,
Width和Height是添加宽度和高度的约束,可以添加大于等于,等于,小于等于。
Horizontal Spacing和Vertical Spacing,
只有选择了2个View或者以上才能选,这个就是2个或多个View的水平和垂直方向的间隔的约束。
第三个section,分别就是左边离父View的约束,
右边离父View的约束,
顶部离父View的约束,
底部离父view的约束。
最后一个section就是,2个或者多个View的等宽和等高。
Pin里面其实很容易中坑的,再下面我会说一下这里面怎么坑,
还有为什么我开始的时候,就对2个子View命名了。
回到刚刚的问题,为了得到这样子的效果,我们可以:
1、View1和View2 Width Equally
2、View1和View2 Height Equally
3、View1和View2 Horizontal Spacing的约束为5
4、View1 Leading、Top和Bottom Space to SuperView的约束都为5
5、View2 Trailing、Top和Bottom Space to SuperView的约束都为5
这样子,大家可以预览一下,这些约束.
然后分别看一下View1和view2的约束情况
通过图片可以看出来,View1是可以唯一确定它的特征的,
假如说那个框框缺少一些的话,那个View就确定不了它究竟应该怎么去展示了。
既然把约束都写好了,可以去拖动一下看看效果呢。
是不是有点成就感呢。无论在那种屏幕的大小下面,布局依然不会变,
以后再也不用看到苹果出新款的设备而发愁了。
有人说,一个View有2个子View这种太简单了,
一个View里面有3个子View该怎么设计这个AutoLayout了。
三、自动布局的进阶
问题:一个View里面有3个子View
3个子View分为左,中,右(view1,view2,view3)
1、view1,view2,view3等宽(你们想等高也是可以的)
2、view1离父view的上左下的距离,这里是为5。
3、view2离父view的上下的距离,这里也是为5。
4、view2的center跟父view的center相等(view2肯定是在正中间的)
5、view3离父view的上右下的距离,这里也是为5.
6、分别设置view1和view2的水平间隔是5,view2和view3的水平间隔也是5.
根据以上的思路就可以得到这样的一个约束关系
写好约定之后,记得update一下,Xcode的刷新有点延迟呢。
ok,我们来演示一下3个view的自动布局的效果。
现在问题又来了,假如一个view里面有4个View,也是需要这样子的布局呢,
这种4个应该很常见了,经常4张等宽高的图片这样的布局的。
这个问题也很简单,一个View里面先放2个透明的View作为容器,view1和view2,view1和view2,
用刚刚说的方法去做布局。
在view1里面呢,也放2个view,分别是view1-1和view1-2,
在view1里面重复刚刚做的方法去做布局,同理在view2里面也是这样子做。这样子就可以得到了。
演示效果:
那假如一个view里面有5,6个呢,这个也是很简单的,
自动布局,就是要把能定的定下来,不能定的用已经定下来的去约束它,
这样子就可以得到一个很好的视觉效果了。
刚刚说到Xcode里面有坑的地方,其实是个人的一个不好的习惯问题,
很多人拖拽控件到xib里面,不会对控件命名的,比如view还是view,
不管是1个view还是n个view所有的都是view,那么这样子会带来一个比较郁闷的后果,
就是在填写约束的时候,你不知道这个约束是哪2个view之间的。
假如写错了,你不知道怎么去通过写好的约束中,找出哪个是写错的,
如上图,就非常清晰,哪个view相对于哪个view是水平间距还是垂直间距,就很清楚了。
假如你没有命名的话,就所有都是view-view了,
这样子要找出来这些约束是什么意思的,就几乎不可能呢。
Xcode里面,特别是选择2个子view之间的布局关系的时候,那边填写约束的时候,要认真看清楚,
是哪个view的什么位置相对于哪个view的什么位置,约束是多少。
很多人之所以可以做到效果,是因为刚好就对了,
而我就是这个倒霉的人,试了一个晚上都没对,后面血的教训,教育了我一定要写好命名。
这里面只是AutoLayout的应用的一个部分,
主要是要让大家理解AutoLayout的原理,以及配合xib去写界面,调试界面。
如果有不了解的,可以发邮件给我。