iOS使用autolayout和sizeclass 解决适配问题(一)

jopen 9年前

   刚接触autolayout的时候我们不禁会问我为什么要使用autolayout  我使用frame 照样可以写项目为什么要用autolayout呢?

一。为啥使用autolayout?使用 autolayout 有什么好处?

随着iPhone的种类不断增多,不同尺寸、不同分辨率的iOS设备将会越来越多,使用传统frame布局的工作量必将越来越大;加上苹果发出的信号,使用autolayout势在必行。

好了,那么autolayout了,它到底能解决什么问题,给我们带来哪些好处?

1)你基本上可以不用考虑苹果设备的各个屏幕不同分辨率的问题,你终于可以不用在viewDidLoad方法里判断不同分辨率下,不同控件应该放在哪里,或者针对不同分辨率写不同的storyboard和xib;

2)你可以抛弃那些根据不同文字来计算tableViewCell、UILabel高度的代码了,因为autolayout会帮你自动计算好;

3)如果你的布局在横屏竖屏下变化不是特别大,你不用再为横着竖着写两套代码或者写两个storyboard/xib了;

4)对于市面上的4.7寸和5.5寸iPhone或者其他尺寸的iPhone或者苹果系列的设备,你基本上能很快甚至不用动一行代码就完成他们的自适应屏幕布局,不用每次来了新分辨率,你只能say f*ck,然后改两个通宵。

再看看苹果的态度,默认就是选择了使用autolayout。虽然我现在仍有时会骂autolayout,但我还是会坚决地选择走上这条道路。

二。 autolayout 和sizeclass  两者 有什么区别吗?

首先说autolayout ,如果你选择了autolayout 而没有选择sizeclass,那么你默认的所加的约束就是在iPhone或者ipad 上运行。具体操作见下图:

xcode 在我们创建工程的时候已经默认的为我们选了 autolayout 和sizeclass ,由此可见苹果是希望我们用两者结合 来开发应用的。

我们不使用sizeclass 的时候 显示的是这个样子的:


</div>

那么使用了autolayout 和sizeclass 的是么状态呢?


</div>

ok,我们可以看到上面就是采用了autolayout和sizeclass 之后的布局了。主要分为9种:宽(正常,任意, 紧凑),高(正常,任意, 紧凑)3x3共9种Size,每种Size都可以设置特定的一套布局,如果不特殊指定,默认是在(宽任意,高任意)模式下设置,且其他8种布局继承它。因为Size Class在将屏幕分类后,执行布局的还是Autolayout。

假如iPad和iPhone的布局有差异,老式写法是分成ipad.storyboard和iphone.storyboard来分别写,这本身就是个bug,因为大部分控件其实并没差别,新Size Class解决这个问题了没?答案是肯定的,XIB中某个View的出现与否,约束的出现与否以及约束的值都是可以根据Size Class单独设置的,也就是说现在一个storyboard是9合1的。比如有个Label,我只希望它出现在长宽紧缩的屏幕上时(脑补iwatch),这么勾选下就可以(出现或不出现被命名为”Installed”,这个选项可以从9个Size Class中多选。

通过下图可以清楚的看到这九种不同的类型 对应 的设备。


</div>

</div>

如上图可以看出我们installed 之后 ,我们的label 正常显示 ,左边视图的层级中label显示的是黑色。表示在当前选择的any(任何设备) 上正常显示。

当我们取消勾选installed 之后 会看到左边视图层级中label显为灰色。 然后storybord 上面就不显示了。其实这个显示与否,只是说我们在特定的设备上显示或者隐藏。


</div>

通过上面的例子也许你已经知道我们为什么要用sizeclass了。sizeclass的好处也是显而易见的。

三。 我理解的autolayout

废话不多说了,通过自己使用autolayout 总结自己理解的autolayout。仅仅是个人理解如有雷同,纯属巧合。

这里姑且把我们的手机或者模拟器比作一个竖直方向放置的的黑板,我们的控件就相当于放在黑板上的一件东西,它可以用绳子固定在上面。我所理解的加约束就是:有一个物体悬空放到黑板上与黑板接触然后用绳子能固定住,绳子不能用多也不能用少。用得多了浪费并且还可能会产生冲突。用得少了,不能正确的固定位置然后还可能导致在你移动的时候可能会找不到位置(就是说这个物体在你的约束下不见了)。 说这么多还不如实战。下面通过一些例子来说明约束的可操作性和便捷。

四。实践

1.ok ,下面实现一个简单的就是一个label 在屏幕在正中间。

我们需要加的约束是让这个label 在x轴中心 在y轴中心。

约束见下图


</div>

1).其中 Horizonetal Center in Controller  指的是“在水平方向居中 相对于它的父视图。后面的数字表示是偏离中心多少。

2).下面的Vertical Center in Container  指的是 在竖直方向居中 同样相对于父视图。 后面的数字同样表示是偏离中心多少。

我们在加完约束之后会发现出现了黄色的tips。这些黄色的tips 是怎么出现的呢。 看下图:


</div>

1).其中 update Frame 表示的是我们根据约束来更新frame。

2). update constraints 就是我们根据当前的frame 来更新约束。

3).第三个reset to suggested  constraints 表示是清空当前约束,然后重新设置成系统为我们建议的约束(这个约束不建议使用)

4).下面的apply to all views in container  表示的是 把所选约束或者frame的改变应用到容器中的所有view中。

这里选择第一个 因为约束已经加好,只需要更新下frame就好。

补充说明一下:为什么要更新frame:因为我们在拖控件的时候不可能一下子就拖到我们想要的位置。这就需要我们先加好约束,然后根据约束来更新frame。

我们使用了sizeclass 那我们来看下效果。 在iPhone 和ipad 上的效果

右边是6p


</div>

</div>

下面是ipad


</div>

通过上面三个图 我们可以看出我们使用一套界面就可以对iphone ipad 进行适配。要做真正的适配这些是还不够的还需要图片的配置。因为不同设备下对图片对分辨率的要求是不一样的。

2。第二弹

这个例子实现的效果:两个视图 等高等宽间距固定(80)。并且视图距离上边界30 距离左边界/右边界 20.

下面看下效果图:

旋转后


</div>

</div>

遇到这样一个需求我们应该怎么做呢?当然不能盲目来写。要想好采取什么样的约束。首先距离上边界和距离左右边界的约束不难,等宽等高这个约束要考虑到。不能固定宽和高的大小,如果固定了根据当前的需求不能满足两者的距离是80.如果不固定宽高的话,那么我们得到视图的宽高就是固定的。还有就是相对位置的问题,A固定以后,B加的约束跟A有关那么B加的约束就是相对约束。就拿蓝色view 和红色view 来说吧,要想实现两者在同一水平线上 其中红色view 距离父视图顶部30是固定的。我们有两种方案1.我们可以直接设置蓝色view距离父视图也是30.这样同样可以解决问题。2.由于红色视图是固定的,蓝色view 的TOP和 红色view 的TOP在同一水平线上也能实现效果。

两种方案都可以实现效果,那么我们应该怎么选择呢?首先我们要从代码维护成本来说,在两者都能完成目的的情况下,低成本的应用维护才是目的。我们采用方案一的话如果我们想修改距离上边界的约束。那么我们就需要修改红色和蓝色view 的约束。我们需要修改的约束有两个。采用方案二的话我们只需要修改红色view 距离上边界的距离就好。因为蓝色view 是相对于红色view来设置约束的。这样维护的成本会降低。

具体操作可查看demo  地址 :https://github.com/shaveKevin/AutolayoutAndSizeclassPartOne.git

下面就加的约束来进行解释.


</div>

标注⑦表示的是 这是红色view  下面的约束对应的也是红色view 的约束。

① .约束一 表示的是 红色想第一自己 的宽高比是1:1 因为这里需要的是狂傲相同。当让这个可以根据不同的需求来设置不同的宽高比。

②.约束二表示的是蓝色和红色的TOP 也就是顶部在一条水平线上。写这个约束的时候,首先把红色的确定,然后让蓝色相对红色来加约束。(也就是说这个约束是加在蓝色view上的 因为约束是相对的,比如说我的位置是固定的,假设两人面对面间距5m,也就是说你在我正前方5m,那么我再你正前方也是5m ),使用的多了,也就明白约束的相对性.

③.约束三表示的是 蓝色view相对红色view 宽度是相等的。

④。约束四 表示的是红色view距离父视图左侧的距离是20.

⑤。约束五 表示的是红色视图右边界与蓝色视图的左边界的距离是80  就是说两个视图间距80.

⑥。约束六 表示的是红色视图的顶部相对于父视图来说距离是30

下图的标注的是蓝色view 的约束。


</div>

①。约束一表示的是蓝色view 相对自己的宽高比是1:1

②。约束二表示的是蓝色view 和红色view顶部保持在同一水平线上

③。约束三表示的是蓝色view相对红色view 宽度是相等的。

④。约束四表示的是蓝色view距离父视图右边界距离是20

⑤。约束五表示的是蓝色view 的左边界距离红色view 的右边界距离是80 。

上面的描述纯属个人理解,如果描述的不对,请指出。

(例子不断增加中。。。)

五。总结。

//未完待续。。。

六 参考博客

http://segmentfault.com/a/1190000000646452从此爱上iOS Autolayout

http://blog.sunnyxx.com/2014/09/09/ios8-size-classes/iOS8 Size Classes初探

七   demo 地址 

iOS开发交流群:214541576

来自: http://www.jianshu.com/p/7a75b8942f0e