一、关于自动布局(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组件是由一个个相对独立的可视单元构成,这些可视单元有的主要负责向用户
输出有用的信息,有些则负责信息的输入(交互),交互的过程中往往还伴随有动画的效果,已达到整个信息传递的连
贯性以及用户体验的细腻感。可视单元,在实际开发中主要是view、button等,那么这些可视单元的关系由两个基本的
关系构成:兄弟关系和父子关系,整个视图单元就是一个树形结构:
对于任何一个UI组件,确定了它的(相对于父view)位置、大小也就确定了它在整个UI视图中的展示效果
Autolayout(以及iOS8中新增的sizeclass)是为了解决这些UI可视单元或者元素是怎样布局、排列的问题。在过去
只有iPhone4的时候,我们可以在代码里将没一个可视单元的位置写死,这样是没问题的,但随着iPhone5、6的发布,
屏幕尺寸有了越来越多中可能,未来不排除更多尺寸的iPhone发布出来,这就要求我们的APP的UI元素具有在屏幕尺寸
不同的设备上具有一定动态的可调性,已实现较好的UI展示效果。从目前苹果提供的技术来看,有下、中、上三种实现
方法:
下策是,代码中判断当前设备的尺寸,对UI元素进行手工的调整,其缺点是显而易见的:代码复杂、容易出错、且
维护难度大、灵活性极差;
中策是,通过设置可视单元(UIView UIButton...)的autoresizing属性,预设当该view所在的环境(父view)发生变化时它的尺寸和位置应该如何调整,该方法可以在Xcode的interface builder中(storyboard或者 xib)设置完成,但其只能针对父子关系进行有限的调整,比如左边距是否固定,尺寸是否可变等,而对于兄弟关系的调整则无法实现,对于UI比较固定的APP这种调节方式也算基本满足需求;
上策就是结合使用autolayout和sizeclass对UI可视单元的父子关系、兄弟关系进行全方位的调整,而且调节精度更高:不仅能确定一个view的位置尺寸的变化依据是什么,还能对这些依据加以不同的优先级,先满足什么条件,再满足什么条件,对于重要的位置尺寸可以优先保证,这样整个APP就具有极强的动态可调性,满足不同设备、不同应用场景下的需求。
在目前苹果手机苹果尺寸多达四种的情况下,显然新的APP必须要采用上策来解决视图组件的布局问题。
Autolayout的作用非常明确:帮我们确定在不同设备、不同(父view)环境下,同一个可视单元所应具有合适的位置和尺寸,因此,当一个UIView上所施加的约束能够唯一确定它的frame(x, y, width, height)的时候我们的自动布局的使用才是正确的。而新手通常犯的两类错误就是约束不足(约束太少)和约束冲突两种(约束太多)。如果你给出的约束只能够确定这个view的大小,或者位置或者位置中的某一个项(比如x)的时候,就会出现约束不足的情况,在xib或者storyboard中,会以黄色的警告出现在左侧提示框内;如果你给出的约束推导出了两个甚至多个互相矛盾的位置尺寸结果的时候,就产生了布局错误,在编译的时候直接就build不过。
二、关于iOS8新增的sizeclass属性
在iOS8中,新增了Size Classes特性,它是对当前所有iOS设备尺寸的一个抽象,也是该抽象了,想想现在多少种i
OS尺寸的设备吧:iPhone4-5-6-6plus、iPad、iPad mini、iWatch,如何还是按照以前那针对种特定设备来编写不同的
布局的话,一定是很糟糕的一件事情。现在有了sizeclass,事情就好办多了:你不是设备多吗,那我们就只把屏幕的宽
和高分别分成三种情况:(Compact, Regular, Any),也即紧凑、正常和任意。这样宽和高三三一整合,一共9中情况
。如下图所示,针对每一种情况,如果需要的话,我们可以单独在storyboard或xib中设置UIView的自动布局约束,甚至
某一个button是否显示都是能轻松实现。
关于size class的详细解析,参考苹果文档和wwdc2014视:点击打开链接 (What's New in Interface Builder)。
三、storyboard种autolayout和size class的无敌配合
对Xcode的interface builder比较熟悉的童鞋应该对UIButton的超强定制性映像深刻:通过选择button的不同状态(normal、height、disabled...),我们可以单独设置每一种状态,button的background image、image、text color等属
性,见下图:
一种或几种分别进行自动布局的设置,这样,当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采用正常的上下结构;横屏时则采用左右结构。
二、竖屏布局
三、横屏布局
为了布局方便,我们首先将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对界面重新布局的效果,相当给力:
四、总结