xcode6中自动布局autolayout和sizeclass的使用

本文介绍了如何在Xcode6中使用自动布局和尺寸类(SizeClasses)解决不同设备和旋转方向下的布局问题,通过实例演示了如何根据不同尺寸类设置布局约束,以实现灵活的UI布局。

一、关于自动布局(Autolayout)

hi,all:

在经过了一番犹豫之后,我决定将我自己做的这个小APP的源码公布给大家:

其出发点是和大家一起学习iOS开发,仅供学习参考之用。之前代码是托管与gitlab

上的,今天我将其pull到github上来了,大家可以自行下载:git clone git@github.com:lihux/twentyThousandTomatoes.git没有安装git或者不会用的童鞋,

请猛戳github地址:https://github.com/lihux/twentyThousandTomatoes,进去之后选

择download zip下载即可。


Xcode中,自动布局看似是一个很复杂的系统,在真正使用它之前,我也是这么认为的,不过事实并非如此。

我们知道,一款iOS应用,其主要UI组件是由一个个相对独立的可视单元构成,这些可视单元有的主要负责向用户

输出有用的信息,有些则负责信息的输入(交互),交互的过程中往往还伴随有动画的效果,已达到整个信息传递的连

贯性以及用户体验的细腻感。可视单元,在实际开发中主要是viewbutton等,那么这些可视单元的关系由两个基本的

关系构成:兄弟关系和父子关系,整个视图单元就是一个树形结构:



对于任何一个UI组件,确定了它的(相对于父view)位置、大小也就确定了它在整个UI视图中的展示效果


Autolayout(以及iOS8中新增的sizeclass)是为了解决这些UI可视单元或者元素是怎样布局、排列的问题。在过去

只有iPhone4的时候,我们可以在代码里将没一个可视单元的位置写死,这样是没问题的,但随着iPhone56的发布,

屏幕尺寸有了越来越多中可能,未来不排除更多尺寸的iPhone发布出来,这就要求我们的APPUI元素具有在屏幕尺寸

不同的设备上具有一定动态的可调性,已实现较好的UI展示效果。从目前苹果提供的技术来看,有下、中、上三种实现

方法:


下策是,代码中判断当前设备的尺寸,对UI元素进行手工的调整,其缺点是显而易见的:代码复杂、容易出错、且

维护难度大、灵活性极差;


中策是,通过设置可视单元(UIView UIButton...)的autoresizing属性,预设当该view所在的环境(父view)发生变化时它的尺寸和位置应该如何调整,该方法可以在Xcodeinterface builder中(storyboard或者 xib)设置完成,但其只能针对父子关系进行有限的调整,比如左边距是否固定,尺寸是否可变等,而对于兄弟关系的调整则无法实现,对于UI比较固定的APP这种调节方式也算基本满足需求;

上策就是结合使用autolayoutsizeclassUI可视单元的父子关系、兄弟关系进行全方位的调整,而且调节精度更高:不仅能确定一个view的位置尺寸的变化依据是什么,还能对这些依据加以不同的优先级,先满足什么条件,再满足什么条件,对于重要的位置尺寸可以优先保证,这样整个APP就具有极强的动态可调性,满足不同设备、不同应用场景下的需求。


在目前苹果手机苹果尺寸多达四种的情况下,显然新的APP必须要采用上策来解决视图组件的布局问题。


Autolayout的作用非常明确:帮我们确定在不同设备、不同(父view)环境下,同一个可视单元所应具有合适的位置和尺寸,因此,当一个UIView上所施加的约束能够唯一确定它的framex, y, width, height)的时候我们的自动布局的使用才是正确的。而新手通常犯的两类错误就是约束不足(约束太少)和约束冲突两种(约束太多)。如果你给出的约束只能够确定这个view的大小,或者位置或者位置中的某一个项(比如x)的时候,就会出现约束不足的情况,在xibstoryboard中,会以黄色的警告出现在左侧提示框内;如果你给出的约束推导出了两个甚至多个互相矛盾的位置尺寸结果的时候,就产生了布局错误,在编译的时候直接就build不过。

二、关于iOS8新增的sizeclass属性


iOS8中,新增了Size Classes特性,它是对当前所有iOS设备尺寸的一个抽象,也是该抽象了,想想现在多少种i

OS尺寸的设备吧:iPhone4-5-6-6plusiPadiPad miniiWatch,如何还是按照以前那针对种特定设备来编写不同的

布局的话,一定是很糟糕的一件事情。现在有了sizeclass,事情就好办多了:你不是设备多吗,那我们就只把屏幕的宽

和高分别分成三种情况:(Compact, Regular, Any),也即紧凑、正常和任意。这样宽和高三三一整合,一共9中情况

。如下图所示,针对每一种情况,如果需要的话,我们可以单独在storyboardxib中设置UIView的自动布局约束,甚至

某一个button是否显示都是能轻松实现。



关于size class的详细解析,参考苹果文档和wwdc2014:点击打开链接 (What's New in Interface Builder)

     三、storyboardautolayoutsize class的无敌配合

                                           

Xcodeinterface builder比较熟悉的童鞋应该对UIButton的超强定制性映像深刻:通过选择button的不同状态normalheightdisabled...),我们可以单独设置每一种状态,buttonbackground imageimagetext color等属

  性,见下图:


Xcode6 中对自动布局的重大变更有异曲同工之妙:开发者可以根据实际需要,针对 size class 的九种组合中的某

一种或几种分别进行自动布局的设置,这样,当APP运行于不同屏幕、不同旋转方向的时候,就可以根据当前环境的

size class情况使用我们预先设置好的布局信息,从而达到APP UI的极大灵活性。

和设置UIButton的不同状态的不同属性类似,我们首先选择一种size class,然后针对该种size class进行自动布局。下面我们以一个简单的布局场景为例进行说明:

假设,我们想实现下面这个效果:横屏和竖屏头像和label都能正常的现实,且在比较恰当的位置:显然横屏的时

候,高度处于压缩的状态,(height: compact),我们需要先对正常的布局之外,还要添加一种(wAny, hCompact

size class的布局:

首先,我们对默认的sizeclass进行布局,确定头像和label的位置和尺寸:




设置完(wAny hAny)之后,点击wAny hAny文字(上图底部),选择(wAny hCompact):注意点击后弹出一

个九宫格浮框,拖动鼠标即可选择响应的size class,注意在右下角(红色方框表示),还可以选择是否install,如果取

消勾选,则这个头像在当前size class下就不会被加载(自然也就不显示出来)。




在新的size class下我们开始添加新的布局,注意,这里并没有覆盖上一种size class我们定义好了得布局,知识针对当前的size class添加新的、独立的布局信息,狡兔三窟,Xcode6这下子一口气给了我们九个窟窿,爽!大笑



布局完毕,运行起来,即可达到我们想要的效果!

Awesome, isn't it ?


xcode6中如何对scrollview进行自动布局(autolayout)

在经过了一番犹豫之后,我决定将我自己做的这个小APP的源码公布给大家:

其出发点是和大家一起学习iOS开发,仅供学习参考之用。之前代码是托管于gitlab

上的,今天我将其pull到github上来了,大家可以自行下载:git clone git@github.com:lihux/twentyThousandTomatoes.git没有安装git或者不会用的童鞋,

请猛戳github地址:https://github.com/lihux/twentyThousandTomatoes,进去之后选

择download zip下载即可。


Xcode6中极大的增强了IB中自动布局的能力,下面就通过对刺儿头scrollview进行一次自动布局实战,看看自动布局在Xcode6中到底值不值得使用:

说UIScrollView是个刺儿头,实在没有夸张,这是由于scrollview本身contentSize、contentInsets等复杂的特性导致,苹果文档在讲autolayout的时候甚至专门拿出一节讲如何对scrollview进行自动布局。国外有个哥们曾经那他遇到的布局问题请教苹果员工,结果花费了40分钟才得出可行的办法:

When I had a chance to go talk to an actual Apple Engineer about AutoLayout last week at WWDC, I made sure to go. I thought of my most painful experience using AutoLayout recently – when I was making a login screen with username and password fields on a ScrollView (so it scrolls up when the keyboard comes up) – and had the Apple engineer walk me through the example.......This “simple” solution took the Apple Engineer 40 minutes to solve! However, several senior engineers I know said that they’ve never been able to get AutoLayout working quite right on a ScrollView, so 40 minutes is actually not bad! 【原文地址

一、我们的需求是什么?

我们要如下图实现这样一种布局:


整个视图一共有三个组件:头像(UIimageView)、文字(UILabel)、和一个UIScrollView。我们的布局预期是竖屏是整个view采用正常的上下结构;横屏时则采用左右结构。

二、竖屏布局

为了方便布局,对于在逻辑或者结构上比较紧密的多个视图组件,我们往往采取化零为整的办法,将多个view放在一个containerview中,让这个父view独自去应对外部情况的变化,将内部和外部隔绝开来,本例中,就是将头像和文字label放入一个contanierview中的。这样,我们布局的主要工作就集中在两个组件之间了:头像所在的containerview和scrollview。同样的,对于scrollview中的子view,我们同样也可以将其放在同一个父的container view中,然后将这个container view作为scrollview的子view也即content view,这样我们对scroll view 的布局就可以简化为对content view的布局,而content view里面的子view相对于content view的布局就是普通的布局了,剩下的只需要我们解决好scroll view和content view的布局即可。
打开storyboard,首先对默认的size class进行布局(wAny, hAny)(关于size class的使用,详见我上一篇博文),对头像的container view添加四个约束以确定其frame (x, y, width, height),这四个约束分别是:水平居中、距顶端定长、定宽、定长,布局基本功不再多言,无非点击、选中、设置......详情请参见苹果官文,布局解析见下图:

接下来就是对scrollview进行布局,我们知道scroll view除了自身的布局需要考虑(x, y, width, height)外,还有一个contentSize属性也必须要在布局的过程中进行确定,contentSize是UIScrollView用于确定它所要展示的内容尺寸的大小,而这个contentSize在布局中实际上是又scroll view的子view :content view的宽和高实现的,注意:我们不能将content view的宽和高的约束设定为由scroll view决定(如和scroll view等宽、等高),否则,Xcode会有警告:scroll view的content size不确定!



在这种情况下,我们必须要对content view的布局约束引入scroll view之外其他参照物,我们拖进来一个辅助的view作为参照物or锚点,示意图如下:


在storyboard中,这三个view的层次是:


通过这个参考view,确定content view的宽度和高度,尽管content view的尺寸可以不依赖于scroll view,但我们还不得不设定content view 和其父view的关系:具体而言就是要确定content view和scroll view的top, bottom, leading和trailing contstraints,这个地方可能比较具有迷惑性,原因是苹果对于这四个约束的使用在scroll view中做了变化:它不再是确定content view尺寸的依据,而是帮助scroll view中content view四周的边界(or你可以理解为留白),进而确定scroll view的contentSize属性


这样,默认size class的布局就算完成了,(注:content view的子view的布局这里不再详述)。

三、横屏布局

为了布局方便,我们首先将storyboard中view的尺寸调整为667 * 375, iphone 6 横屏时的尺寸,然后将size class的height设置为compact模式(因为横屏时,高度处于“压缩”状态),这样我们就可以对横屏的状态进行单独的布局,Xcode对自动布局通过size class的使用,灵活性大大提高(详细说明参加我上一篇博文),不同size class下约束相互隔离,甚至另外一个size class下添加的view也是不可见的(not installed),这样我们布局工作起来就大大的简化了。



调整完view的尺寸后将size class设为(wAny, hCompact)

前面需求中提到,在横屏模式我们希望中,将头像和scroll view按照左右顺序布局,这样可以有效的利用屏幕空间,给用户最好的使用体验(尤其是iphone6 & plus出来后)。

考虑横屏的情况,我们不知道屏幕的具体宽度(实际从4s到6 plus可能有4种数值),我们想确定头像和scroll view 的具体位置,这时,我们又要找一个参照物了,有了参照我们就能很好的确定各自的约束。这种参照物的思想在自动布局中有着广泛的应用,它可以有效的帮我们降低布局的复杂度、提高布局的灵活性。

我们仍然选取一个view作为参考物or 锚点,我们把它的位置放在整个屏幕的正中间,这个view我们称之为:middle anchor view,头像的trailing space和scroll view 的leading space就都可以以这个middle anchor view为锚确定x坐标值了。


接着,头像和scroll view以及content view的其他约束可以按照竖屏时的思路依次添加。布局完成后如图所示(红色view即为anchor view,在布局完成之后可将该view隐藏):


注意,因为前面竖屏的时候我们使用了(wAny, hAny)的宽和高都任意的size class,它包含(wAny, hCompact)这种情况,因此,在上一个size class设置的布局元素在当前的size class中依然都存在,为了防止布局干扰,我们可以将这些布局全部清除掉再重新布局:


可以方便的在storyboard中清除全部约束


全部布局完成后,编译运行即可获得前面需求中所示的效果。下面的gif动画展示了由竖屏到横屏时autolayout对界面重新布局的效果,相当给力:


四、总结

1.布局之前考虑好需求是什么,横竖屏时的UI展示效果是什么;
2.布局UIScrollView的时候将其子view放在一个content view中去,简化布局;
3.布局content view的时候必须要引人第三方参照物(view),已确定其尺寸,注意不能根据scroll view 来确定content view的尺寸;
4.一定要设置content view 相对于scroll view 的上下左右(top, bottom, leading, trailing)间距,这些设置不是为了确定content view的尺寸,而是帮助scroll view 确定其contentSize;
5.布局时注意一些小技巧的使用,可时布局工作事半功倍:
a. 将多个view放入一个container view的化整为零思想;
b. 引入参照物or 锚点,辅助定位、布局;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值