原文:http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1
Ray:Matthijs Hollemans iOS7 系列教程坐作者,已经将iOS7的auto layout植入进去了,所以我们希望大家喜欢这片文章。
你以前是否对iphone横竖屏适配感到苦恼和困惑?同时适配iphone和ipad是否使你感到抓狂?哈哈,不要在懊恼了,来看看我给你带来的好消息!
其实,我们设计一个方向的屏幕(一般都是竖屏)的布局是不难的,但是如果有一些应用要求横竖屏都支持,那么所有的UI的大小必须随着设备方向的变化而重新适配,如果的布局设计相当复杂,(哈哈,估计你该哭了)你必须写大量的代码来适配尺寸(有的时候,竖屏写一个,横屏写一个)。但是如果你用了iOS6带来的Auto Layout 结果就不一样了(腰不酸、腿不疼,走了也有劲了,一口气上6楼不喘)。如果你用的Xcode5的ios7来做,这件事情 so easy,如果是Xcode4,哥们劝你放弃吧!给Xcode5一个展示自己的机会吧。(肯定是我水平不够,感觉老外的感情这么丰富)。
Not only does Auto Layout makes it easy to support different screen sizes in your apps, as a bonus it also makes internationalization almost trivial. You no longer have to make new nibs or storyboards for every language that you wish to support, and this includes right-to-left languages such as Hebrew or Arabic.
This Auto Layout tutorial shows you how to get started with Auto Layout using Interface Builder. In iOS 6 by Tutorials, we take this tutorial even further, and then have an entirely new chapter that builds on this knowledge and shows you how to unleash the full power of Auto Layout via code.
Note: We are in the process of updating all of the chapters in iOS 6 by Tutorials to iOS 7 – and this is a sneak preview of that update! When we’re done, the update will be a free download to all iOS 6 by Tutorials PDF customers.
So grab a snack and your favorite caffeinated beverage, and get ready to become an Auto Layout master!
这几段就不翻译了。意思告诉你ios7很"流弊",你要好好学,就能很"流弊"了。
好了上面都是扯蛋,重点现在开始。
1.The problem with springs and struts -- 就是使用springs和struts存在的问题(autosizing masks 这个熟悉吧,就是使用这个目前存在的问题)
想必大家对autosizing masks的使用已经相当熟悉了,换句话说大家对 "sping 和 structs"(伸缩和卡位或者固定位置)布局模式也很熟悉了。当我们所以开发手机软件发生横竖屏切换的时候,这时我们就会用到autosizing masks,那它的自动伸缩,固定位置等是如何做到的呢,又再什么时候用呢?
举个例子来说,我们把一个子View添加到到一个大的View让它们宽度 320px ,同时设置了子View的autosizing masks 为 UIViewAutoresizingFlexibleWidth,当我们把手机横向时候,大一点view宽度编程480px,你会看到子view也会自动适应这个宽度,我们在调整子view 大小为100*100 位置设置为(220,0),就是在竖屏情况的右上角,把autosizing masks 为 UIViewAutoresizingFlexibleWidth改为UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleLeftMargin,我们在把设备横屏,你会发现子view还在(100*100大小不变)右上角。
(上面这段翻译,我做了深一步的解释原文是:For example, with a flexible width the view will become proportionally wider if the superview also becomes wider. And with a fixed right margin, the view’s right edge will always stick to the superview’s right edge.)
很快你就会发现只有,autosizing 方法在简单的布局中是奏效的,但是在复杂的布局方面,这种方法就不是很有效,我们来看一个例子。
用你的Xcode5 新建一个基于 the Single View Application的项目,命名为StrutsProblem:
单击Main.storyboard,用Interface Builder打开,选择完之后,第一步要做的是禁用Use Autolayout(把那个√拿掉),在选项卡File inspector下面:(如下图)
这样这个Main.storyboard就是用以前的struts-and-springs模式。
注意:不要用xcode5.0以下版本来建项目,毕竟autolayout 是 ios6.0及以上版本才有。如果你想在ios6.0以上版本使用autosizing方法,上面已经告诉你了。
从控件库里面托3个view到Main.storyboard上面,如下图(4.0寸的屏幕)
用颜色区分一下各个view,方便辨认。
所有的空隙都是20个像素,比如左上角绿色的部分为(20,20),黄绿间隔20像素等,大家设一下,蓝色view 280px寛,上面两个是130px的寛 ,所有view都是254像素的高。
在模拟器iPhone Retina 4-inch simulator运行如下图(运行是竖屏,手动横屏 Command+-> (方向键)):
(即使运行不是这个效果也不必惊慌,毕竟这个不是自己想要的效果,就是给你看一个错误的结果,因为我运行的时候就不是这个效果)
我们期望的结果是:
好我们用autosizing来设置一下,首先对绿色view设置如下图:
设置的目的是:将上面和左边固定到左上边缘,同时支持上下左右伸缩。
对黄色view进行如下设置:
对底部蓝色view进行如下设置:
再次运行,如下图:
非常接近了,但是还是不如预期,view和view之间的间缝大小不对,同事还可以看到view的大小也不是100%的正确,问题就出在,当superview发生变化的时候,没有什么机制告诉所有view,view和view之间大小是多少,或者,根据superview变化,子view该改变多少大小来适应。
你用了 autosizing masks 是解决不了精确size、位置和间缝的设置的(变化的)。(比如上面三个view间缝都是20px)。
哈哈,为了解决这个问题,牛人说,用代码,是啊你用了好多代码,来看看代码:
(这一大段英文告诉你要用代码解决这个问题,外国人很实在:UIKit sends several messages to your view controllers before, during and after rotating the user interface. You can intercept these messages to make changes to the layout of your UI. Typically you would override viewWillLayoutSubviews to change the frames of any views that need to be rearranged.
Before you can do that, you first have to make outlet properties to refer to the views to be arranged.
Switch to the Assistant Editor mode (middle button on the Editor toolset on the Xcode toolbar) and Ctrl-drag from each of the three views onto ViewController.m:)
上面的步骤是不是很熟悉啊!
写下下面代码
@property (weak, nonatomic) IBOutlet UIView *topLeftView;
@property (weak, nonatomic) IBOutlet UIView *topRightView;
@property (weak, nonatomic) IBOutlet UIView *bottomView;
- (void)viewWillLayoutSubviews
{
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
{
CGRect rect = self.topLeftView.frame;
rect.size.width = 254;
rect.size.height = 130;
self.topLeftView.frame = rect;
rect = self.topRightView.frame;
rect.origin.x = 294;
rect.size.width = 254;
rect.size.height = 130;
self.topRightView.frame = rect;
rect = self.bottomView.frame;
rect.origin.y = 170;
rect.size.width = 528;
rect.size.height = 130;
self.bottomView.frame = rect;
}
else
{
CGRect rect = self.topLeftView.frame;
rect.size.width = 130;
rect.size.height = 254;
self.topLeftView.frame = rect;
rect = self.topRightView.frame;
rect.origin.x = 170;
rect.size.width = 130;
rect.size.height = 254;
self.topRightView.frame = rect;
rect = self.bottomView.frame;
rect.origin.y = 295;
rect.size.width = 280;
rect.size.height = 254;
self.bottomView.frame = rect;
}
}
当屏幕发生旋转时(或者页面进行重新绘制时)候就会调用这个方法,再运行之前还要修改一下autosizing masks:
运行效果达到预期,但是我们却为这个小功能写了这么多代码,但是如果要是更复杂的,还是动态的页面怎么办?
或者我们换个3.5寸模拟器运行一下看看效果,哎呦,之前所有的尺寸都是寄语4.0写的,现在是3.5的,蛋疼了。当然你可以用if来判断,解决这个问题,但是如果是100个页面(10个吧),是不是难受了。
注意:你可以采用两个xib,但是也不是一件轻松的事情,在不同方向调用不同的xib。不过这样你需要花大力气来维护。
既然说了这么多的autosizing的不好,肯定有很牛逼的东西来代替,这就是Auto Layout to the rescue!
2.Auto Layout to the rescue! ---- 救世主Auto Layout
你将会看到我们如何用Auto Layout来实现相同的效果,同事不需要写任何代码,首先要从ViewController.m文件中移除函数viewWillLayoutSubviews 。
选中Main.storyboard,在File inspector选项卡中,将Use Autolayout 的check box 在勾上:
备注:Auto Layout是对整个的xib和storyboardfile起作用的,所有这个xib和storyboard的子view都会使用Auto Layout。
首先,上述修改完之后,运行一下,在旋转一下屏幕,结果是这样的:
让我们在这些view上添加一些Auto Layout的约束(Constrains)看看,同时选中绿色view和黄色view,确定这个两个view都选中了,下一步操作Editor->Pin->Widths Equally:
确保再次选择这两个view,然后操作是:Editor->Pin->Horizontal Spacing:(第一次操作完成后,会自动取消选中)
由于时间关系,先介绍到这里,未完............不好意思啊...........请看下一节了