学会爱上iOS自动布局(Auto Layout)
本文翻译自Yari Dareglia的LEARN TO LOVE AUTO LAYOUT文章
先生们,女士们,让我们以正确的心态开始本教程吧:自动布局就是简单!
我花了一段时间来掌握自动布局是如何工作的,现在回头看,我发现我绝对是高估了这个问题。在这篇文章中我将介绍一些基本的方面和一些技巧,我敢肯定会帮助你在面对自动布局时不在害怕。
Xcode4
在Xcode5之前,自动布局可能是你在你的应用中实现的最讨厌的“功能”。标记“使用自动布局”就像说“把我变疯吧”。这就是为什么我从来没有对这个标记打勾。为自己感到可耻!
但是在Xcode5中,情况变得完全不同了,如果你仍然对Xcode4中的自动布局做恶梦,好了,忘记他们!
简单描述一下自动布局
通过自动布局,你可以利用UI元素之间的关系来组织你应用的界面。这些关系称为约束。
一开始,这听起来很难懂,因为我们都是独立放置每个子视图的,仅仅需要考虑修改frame/bound属性来决定子视图在哪里以及怎么绘制即可。
这就是本文的第一个目标:抛弃过时落后的习惯!
介绍Xcode5中自动布局的界面
我们可以通过代码或者Interface Builder工具的帮助来设置自动布局的关系。我会在接下来的例子中介绍代码的形式设置自动布局,但现在我们只是介绍Xcode提供的可视化设置界面,从而让事情变得简单些。
创建一个新的iOS工程,打开故事板(storyboard)。在右下角你可以看到一组关于自动布局的按钮。我会在下面的代码中解析其中这些按钮的作用,现在仅仅记住这些按钮是关于自动布局的即可。
另一种方法是直接通过视图来与自动布局交互。把一个UIView拖动到视图控制器上后,按ctrl +单击UIView并拖动鼠标 。你应该看到一个蓝色的选择。你已经对这些很熟悉了,因为它跟我们用来连接IBOutlet/ IBAction是一样的,但是这个时候如果你在新的视图里面(也就是刚刚拖动的UIView里面)释放它,你会看到一些新的选择。
让我们为刚刚创建的视图添加一个约束。*1. Crtl+点击视图的上面
*2.拖动鼠标保持一个水平轨迹。这确保了“宽度”参数显示出来。当你在同一个视图中释放鼠标按,你可以尝试垂直移动,以获得高度参数(我个人觉得这种行为是具有良好的用户体验的一种选择)。
*3.选择“宽度(Width)”参数
现在,您已经创建了一个约束,意思是:“这个视图的宽度是多少”。不必理会被绘制在视图中的红色/橙色线。我们只需要这个约束来看看一些其他的Xcode功能。
选择这个UIView,并在右边栏打开Size Inspector控制面板
你会发现一个叫约束的新区域,在我们的例子中包含了我们刚刚添加的宽度约束。
注意:有些时候,你不会看到宽度或高度约束参数,而是发现一个“Leading space to”的东西,这只是一个bug,取消选择,再重新选择对应的视图,就可以获取正确的参数。
从这里开始,你可以通过旁边的设置图标来修改这个约束或者删除约束。
另一个你可以找到关于你的约束的信息可以在文档大纲中找到,在故事板的左边,你可以通过点击下面的按钮来开启这个栏目
正如你说看到的,我们可以完全浏览所有刚刚创建的约束。点击它,约束将在视图编辑器中高亮显示。 我们从文档大纲中得到的另一个有用的信息是,设置的约束是否有不一致或者错误。在文档大纲右上角出现的红色圆圈和白色箭头告诉我们,有些约束没有设置正确。
点击那个箭头,一个新视图会显示出来并展示相关的细节和错误。
只要按一下第一个红点。 Xcode足够聪明得会建议你正确的自动布局配置。点击“添加缺少约束”,Xcode会自动将一些约束参数添加到视图中,所有的错误都将消失。
如果你再次点击这个视图,你会看到你的约束,但这时这些约束将会变成蓝色。这意味着所有所需的约束都已经定义完成,自动布局完全明白怎么绘制你的视图。
例子0:介绍约束
现在你知道如何与Xcode交互,以管理约束,我们可以使用自动布局练习和学习它是如何工作的。
我们应该牢记的主要规则是,通过自动布局指定一个视图的位置,我们需要给它的X / Y位置和宽度/高度尺寸的约束。这是正常工作的第一步。
打开本教程的工程文件,并检查主故事板的Example_0 Result控制器。您可以通过文档大纲窗口来轻松地在所有的实例中切换。
这是第一个例子的最终结果:一个UIView在垂直和水平方向始终处于中心位置,而不管屏幕的大小的旋转方向。
现在,您可以创建自己的项目或者干脆用我的(你可以在文章的末尾找到源代码)。在这里,我已经创建本教程(命名EXAMPLEN START)的所有例子和最终结果(名为EXAMPLEN结果)的初始设置。
把眼光移到 EXAMPLE_0 START
*1.在这里,你可以找到一个作为主视图的子视图的黄色UIView。我设置了视图大小为150X150,我把它放在X 85和Y209(只是跟着蓝色导航线)。 我喜欢的做法是:在添加任何约束之前,我们定义视图的大小和位置。只有在这些初始设置完成后,才开始设置约束。
*2.现在,让我们使用2种不同的方法来添加尺寸约束。 正如我们在上一节中所做的,CTRL +单击新的视图和水平拖动鼠标来添加宽度约束。
现在,加入高度约束,我们可以使用右下角的图标。首先选择黄色的UIView,然后单击带有“+”标志的“高度”参数的图标,然后单击“添加约束”按钮。这只是另一种方式来设置一个约束。
我们已经定义了这个大小约束了。
*3.在文档大纲中点击红色圆圈,来获取关于我们的视图设置的问题。
正如我所说的,我们需要设置宽度/高度和X / Y以符合自动布局要求的条件,同时Xcode也会帮助我们强调当前还有什么没有设置。
我们可以叫Xcode帮我们自动解决这些错误,与我们之前点击“添加缺少约束”按钮或者是手动添加效果一样。这次就让我们手动添加吧,来看看怎么在父视图和子视图之间创建关系。
同样,我们可以选择两种方式来添加约束:
Ctrl+ 点击UIView视图,但这次是把鼠标保持垂直轨迹来拖动到这个视图的父视图才释放。
选择“Center horizontally in the container”。你可以在名叫“align Center X to: Superview”的大小检查器中验证这个新的约束。
为了添加垂直(Y)的约束,我们使用显示对齐约束选项的第一个图标。点击这个按钮,勾选“Vertical center in container”标记,最后点击“Add Constraints”来确认添加。
你应该看到两个新的蓝色线穿过这个视图,现在所有所需的约束都已经创建了。
*4.启动应用,并在横屏和竖屏的模式之间切换。
太好了,黄色视图都停留在中心位置。
(你可以通过去掉约束来查看之间的不同,在横屏模式下,这个视图会跑到屏幕外面去。)
Xcode帮助
另一个有趣的特点是Xcode在自动管理你的自动布局设置时所具有的重置frames和约束的能力。
在之前设置的约束中,移动黄色视图到一个新的位置(仅仅在大小设置面板中输入X=120,Y=240,而不需要改变约束)。你应该看到类似下面的画面:
你的位置约束变成了橙色,代表这个视图错位了,一个红色的,高亮的虚线正方形表示视图期望的位置,而两个标签显示当前视图与期望视图位置的距离。
在文档大纲中,可以看到很多信息,这时指示器不是红色了,而是橙色,表明这是视图错位是一个警告,而不是错误。事实上,自动布局约束仍然有效,即使你所看到的故事板的内容和运行的结果不同。
那么,我们怎么解决这个问题呢?首先你需要确定你想要的结果是什么。
你希望保持原始的设置吗
如果是,点击下面的按钮:
然后选择“update frame”,这个视图会移动到运行时的位置(红色虚线的位置)。
你希望更新运行时的位置吗?
这种情况,同样点击上面的按钮,选择“update constraints”来改变约束适应当前的位置。
动手试试,看看两者之间的不同吧。
例子1:固定内容大小
好了,转到EXAMPLE1RESULT视图控制器。
在这个例子中,我们希望用UILabel来获得像EXAMPLE_0的结果。
移到EXAMPLE_1 START,然后仅仅添加一个位置约束(如果发现自己不知怎么做,可以回去查看上面例子的第三个步骤)。
是的,你完成了!你可以通过启动应用来检查结果。这个标签完全放在窗口的中间。
等一下,你可能会问,那大小约束不用像上面那样设置吗?是的,我们不需要!而且,设置大小约束将被视为错误。
类似按钮和标签这些对象,是根据他们的内容来决定大小的。一个特定的方法
在这个教程中,我们不讨论自定义视图的自动布局,但是,如果你想创建一个自动适应大小的视图,你应该更深入地理解这个方法。
例子2:与屏幕尺寸独立的UI
当我们为3.5寸和4寸屏幕创建视图,或者为横屏和竖屏创建约束时,都会不同。
转到EXAMPLE_2 RESULT。我想像你展示一个真的很普遍的情况:设置一个可以在任何屏幕尺寸和屏幕方向下都可以正常工作的布局。
分别在iPhone4和iPhone5下运行应用,并改变屏幕方向。你将看到布局都完美地适应屏幕的大小。
你已经知道怎么把一个标签放在中间了,但是那个在屏幕底部的蓝色视图呢?让我们转到EXAMPLE_2 START。你可以如练习中那样设置这个标签,而这个蓝色视图有两个我们必须考虑的方面:
- 它的宽度根据屏幕的大小而改变
- 他贴在屏幕的底部
让我们记住的第一条规则,我们必须同时满足的位置和大小的约束。
*1.首先第一件事情,通过移动屏幕底部的蓝色视图设置所需的位置。
*2.我们可以轻松地设置高度约束只是(按Ctrl+单击)垂直拖动视图并选择“高度”或底部的图标,因为我之前已经向您展示了。
*3.那宽度呢?我们希望它与父类视图有关系,为了做到这点,我们需要创建两个关系:
*保持它的左边与父类的左边距离在N的距离*保持它的右边与父类的右边距离在N的距离
这两个关系会根据它父类的大小变化而自动设置它的宽度。
为了创建这些关系,我们可以Ctrl+点击蓝色视图,移动到左边的父类视图中释放,同时选择“ leading space to container”以及在右边选择“trailing space to container.”。
这时,我们已经满足了所有的大小约束了,接下来让我们设置位置。
*4.再一次,我需要为蓝色视图,定义一个指向父类视图的约束。这非常简单,关系仅仅是:
*保持它的底部与父类的底部距离为0
这个信息足够定义了这个视图的在垂直方向的位置了,因为父类的位置总是已经定义了。
所以我们如之前做的那样,添加这个约束:ctrl + 点击视图,拖动到父类的底部,然后选择“bottom space to bottom layout”(你可以在蓝色视图上释放鼠标)。
注意:你也可以直接在文档大纲中拖动,这种情况下,你可以看到所有可能的约束。
这时,我们所需要的所有的关系都可以满足你的简单界面的需要了。
例子3:代码中更新约束
有些时候,为了更复杂的界面位置,我们需要控制更多的约束。而约束就是一个NSLayoutConstraint类的实例,我们显然可以通过代码,在运行时访问约束相关的属性。
转到EXAMPLE_3 RESULT。你将会看到一个白色的标签对齐于一个红色视图。如果你运行这个实例,你切换横屏和竖屏时,这个红色视图会根据屏幕大小来改变它的高度。
让我们看看怎么做到这个的!
*1.移动到EXAMPLE_3 START *2.添加底部红色视图的约束
*设置与父类的Leading Space 和 Trailing Space,根据父类来定义宽度
*设置与父类底部的空间,使红色视图的底部固定在父类上。
*设置高度(记得吗?ctrl + 点击 ,垂直线轨迹)。
如果你完成了上面的步骤,结果因为像下面的一样,有蓝色约束线:
*3.填加下面的约束给UILabel
*水平居中标签(Ctrl + 点击标签,水平拖动,释放鼠标后选择正确的约束)
*定义一个标签与底部视图的距离(Ctrl + 点击标签,拖动到底部的视图然后放开,接着选择“Vertical Spacing”)。
现在你应该也定义了UILabel所需要的约束了。
这时如果你运行这个例子,你将看到底部的视图没有在垂直方向上自动调整大小。确实,我们并没有设置任何约束来让它这样,那么就让我们设置吧。
*4.我已经把ResizerViewController类关联到这个视图控制器了。打开ResizeViewController.m,你将会看到第一个属性:
*5.让我们关联这个Outlet到刚刚添加的高度约束。
所以再次打开Storyboard,从文档大纲中,在EXAMPLE_3 START行上面 ctrl + 点击,并拖动到高度约束,释放鼠标,这样就可以关联起来了。
现在我们只需要更新这个约束的值就可以了。
*6.打开ResizerViewController.m 文件,并检查这个函数:
1
2
3
4
5
6
7
8 |
- ( void )willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:( NSTimeInterval )duration{ if
(UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) { self .CS_BottomView_Height.constant = 100; } else { self .CS_BottomView_Height.constant = 330; } [ self .bottomView setNeedsUpdateConstraints]; } |
这个函数里,我们仅仅根据设备的方向,来更新这个高度约束的常量属性。
如果运行这个实例,你将看到想要的结果。
结尾
从我自身的直接经验,我在本教程向你展示的就是你开始使用自动布局所需要的所有知识,当然,还有很多其他的自动布局功能值得研究,如“优先级”,自动布局的虚拟格式语言和NSLayoutConstraints的一些更高级的应用。我可能会在以后的帖子介绍它们。
一如往常,敬请期待并感谢您的阅读。
下载源码*