对程序员来说,使UI 组件排列整齐总是一件很头疼的事。如果再加上屏幕旋转,嗯~好吧。不过在iOS 6以后,苹果使这些事儿都变得简单了,因为有了自动布局(Auto Layout)。
·限制条件是在一个视图和其的父视图之间的,那么将限制条件添加到其父视图中。
·如果限制条件是两个不共享同一个父视图的视图之间的,那么将限制条件添加到这两个视图的公共父视图中。
![]()
![](https://img-blog.csdn.net/20140321151926640)
我们来看一个问题。
假设有一个按钮,你想把它放置在屏幕的中央。视图中心和按钮中心的相对位置可以简单地定义成如下:
·按钮的center.x 相当于视图中心的center.x
·按钮的center.y 相当于视图中心的center.y
苹果发现很多的UI 组件的位置可以使用一个简单的方程等式得到解决:
Object1.property1=(object2.property2*multiplier)+constant value ——公式
例如:使用这个方程式,我们可以很容易地将一个按钮放置到他的父视图中,如下所示:
Button.center.x=(button.superview.center.x*1)+0
Button.center.y=(button.superview.center.y*1)+0
·按钮的center.x 相当于视图中心的center.x
·按钮的center.y 相当于视图中心的center.y
苹果发现很多的UI 组件的位置可以使用一个简单的方程等式得到解决:
Object1.property1=(object2.property2*multiplier)+constant value ——公式
例如:使用这个方程式,我们可以很容易地将一个按钮放置到他的父视图中,如下所示:
Button.center.x=(button.superview.center.x*1)+0
Button.center.y=(button.superview.center.y*1)+0
使用这个方程式,你可以在进行UI 开发是做一些很有意思的事情,而不用像以前那样麻烦了。
前面涉及到的公式被封装到了iOS SDK 中的NSLayoutConstraint 类中:
constrainWithItem:attrinbute:relatedBy:toItem:attribute:multiiler:constant:
方法中的参数都有:
constraintWithItem
这是一个id 类型的参数代表之前方程式里的object1。
Attribute
这个参数代表方程式里的property1,并且应该是NSLayoutAttribute 类型的。
relatedBy
这个参数代表方程式里的equals。这个参数的值是NSLayoutRelation 类型的。并且你即将会知道,在这里你不仅可以将其指定为等号,也可以将其指定为大于号或者小于号。我们将会这在章中详细讨论。
toItem
constraintWithItem
这是一个id 类型的参数代表之前方程式里的object1。
Attribute
这个参数代表方程式里的property1,并且应该是NSLayoutAttribute 类型的。
relatedBy
这个参数代表方程式里的equals。这个参数的值是NSLayoutRelation 类型的。并且你即将会知道,在这里你不仅可以将其指定为等号,也可以将其指定为大于号或者小于号。我们将会这在章中详细讨论。
toItem
这个参数是id 类型的,在这个方程式里代表object2。
Attribute
这个参数是NSLayoutAtribute 类型的并且在此方程中代表property2。
Multinlier
这个参数是CGGloat 类型的并且在此方程中代表multiplier。
Attribute
这个参数是NSLayoutAtribute 类型的并且在此方程中代表property2。
Multinlier
这个参数是CGGloat 类型的并且在此方程中代表multiplier。
Constant
这个参数也是CGFloat 类型的并且在此方程中代表constant value。
创建好约束条件以后,你可以将其添加到相应地View中。
约束添加的方法如下:
addConstraint:
这个方法可以将单一的NSLayoutConstraint 类型的限制条件添加到视图中。
这个方法可以将单一的NSLayoutConstraint 类型的限制条件添加到视图中。
约束添加的原则如下:
·如果限制条件位于一个公共的父视图的两个视图之间的,意味着这些视图具有相同的父视图,那么就将限制条件添加到父视图中。·限制条件是在一个视图和其的父视图之间的,那么将限制条件添加到其父视图中。
·如果限制条件是两个不共享同一个父视图的视图之间的,那么将限制条件添加到这两个视图的公共父视图中。
这里有张图,更加直观:
现在我们来实践一下:
问题
你想将一个UI 组件放置到屏幕的中央。换句话说,你想你想将一个视图放置到其父视图的中央位置,使用限制条件。
方案
创建两个限制条件:一个是将目标视图的center.x 位置排列在其父视图的center.x 位置,并且另外一个是将目标视图的center.y 位置排列在其父视图的center.y 位置
首先通过创建一个简单的按钮来开始,这个按钮是将要放置在屏幕的中心的。所要做的就是确保按钮的中央的x 与y 坐标和按钮将要放置的视图的中央的x 和y 坐标一致就行。所以在这里我们将会创建两个限制条件并将它们添加到这两个按钮的父视图中。这里有段示例代码:
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
/* 1) Create our button*/
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
[self.button setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.button setTitle:@"button" forState:UIControlStateNormal];
[self.button setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:self.button];
UIView *superView = self.button.superview;
/* 2) Create the constraint to put the button horizontally in the center */
NSLayoutConstraint *centerXContraint = [NSLayoutConstraint constraintWithItem:self.button
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:superView
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0];
/* 3) Create the constraint to put the button vertically in the center */
NSLayoutConstraint *centerYContraint = [NSLayoutConstraint constraintWithItem:self.button
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:superView
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0];
/* Add the constants to the superview of the button */
[superView addConstraints:@[centerXContraint,centerYContraint]];
}
/* Suport rotation of device to all orientation */
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
这样在任意方向,你的视图都会在屏幕的正中央了。
在button的父视图添加属性之前,调用了[self.button setTranslatesAutoresizingMaskIntoConstraints:NO];这行代码。
下面是文档的解释(重点在黑色文字):
setTranslatesAutoresizingMaskIntoConstraints:
Sets whether the view’s autoresizing mask should be translated into constraints for the constraint-based layout system.
设置view的自适应是否应该翻译成 基于约束的布局系统 的限制。
- (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag
Parameters
flag
YES if the view’s autoresizing mask should be translated into constraints for the constraint-based layout system, NO otherwise.
Discussion
Because the autoresizing mask naturally gives rise to constraints that fully specify a view’s position, any view that you wish to apply more flexible constraints to must be set to ignore its autoresizing mask using this method.You should call this method yourself for programmatically created views. Views created using a tool that allows setting constraints should have this set already.
因为自适应自然产生了 完整的指定视图位置的限制。任何你希望申请更多灵活约束的视图必须用这个方法来设置忽略它的自适应。你需要在编程创建视图时调用这个方法。被创建的视图 使用允许设置约束的工具需要这个方法已经设置好。
好吧,其实主要就是说如果你使用了自动布局,最好取消自适应。
很多事情可以通过Auto Layout 来完成。但是,随着你的深入研究,你就越发现自定布局的设置意味着会产生更多的NSLayoutConstraint类型的限制条件。你会注意到你的代码越来越庞大,并变得越来越难以维护。因此,苹果已经创建了Visual Format language(可视化格式语言),通过它你可以使用简单的ASCII 码来表达你的限制条件。
下一篇将学习用
Visual Format language来实现自动布局。
文中主要内容和代码均来自《iOS 6 Programming Cookbook》,感谢DevDiv热心网友自发组织翻译。