AutoLayout

AutoLayout


前提

  1. 苹果设备屏幕尺寸的碎片化,那么每一种屏幕尺寸都要给界面控件设定一套合适该尺寸的Frame,这种方式想想就够吓人的!

  2. 另外还需要说明的是,如今确实还有不少人仍然使用设定Frame的方式进行布局,并且通过取设备屏幕的宽高进行一定比例的换算确实可以达到正确的定位布局,但是在大多数情况下,如果页面支持屏幕旋转的话,这种设定Frame的方式就完全失效了,旋转屏幕需要做大量的额外处理。

  3. 很多人习惯上是在viewdidload方法中初始化控件(包括init 和设置frame),但是viewController要在viewWillLayoutSubviews的时候才能真正确定view和子view的frame。所以在没有确定view的frame的时候就去操作修改view的frame是不友好的,设置frame的效果也是无法预料的。所以按照这个特性,如果我们用设置Frame的方式布局的话就必须在viewWillLayoutSubviews中重新设定view的坐标大小,布局逻辑会变得更不清晰。

而使用AutoLayout则不会有这些问题。


纯代码与storyboard使用的区别

和自定义View一样

  1. 故事板适合快速写UI 和 界面UI比较简单的时候使用.

    如果UI复杂了,一个XIB里拉满了密密麻麻的约束线,可以肯定的是过不了多久连自己都看晕了。可读性也差。

  2. UI复杂 和 需要复用的时候用纯代码


storyboard使用

简单入门参考 :AutoLayout全解


纯代码使用

使用NSLayoutConstraint
最常用的 constraintWithItem:方法

+(instancetype)constraintWithItem:(id)view1 
attribute:(NSLayoutAttribute)attr1 
relatedBy:(NSLayoutRelation)relation 
toItem:(nullable id)view2 
attribute:(NSLayoutAttribute)attr2 
multiplier:(CGFloat)multiplier constant:(CGFloat)c; 

表示 : view1的某个属性(attr1)等于view2的某个属性(attr2)的值的多少倍(multiplier)加上某个常量(constant)

描述的是一个view与另外一个view的位置和大小约束关系。

其中属性attribute有上、下、左、右、宽、高等,关系relation有小于等于、等于、大于等于。需要注意的是,小于等于 或 大于等于 优先会使用 等于 关系,如果 等于 不能满足,才会使用 小于 或 大于。例如设置一个 大于等于100 的关系,默认会是 100,当视图被拉伸时,100 无法被满足,尺寸才会变得更大。

示例一

一个子view在父view中,其中子view的上下左右边缘都离父view的边缘40个像素。

[self.view setBackgroundColor:[UIColor redColor]];

//创建子view
UIView *subView = [[UIView alloc] init];
[subView setBackgroundColor:[UIColor blackColor]];
//将子view添加到父视图上
[self.view addSubview:subView];

//使用Auto Layout约束,禁止将Autoresizing Mask转换为约束
[subView setTranslatesAutoresizingMaskIntoConstraints:NO];

//layout 子view

//子view的上边缘离父view的上边缘40个像素
NSLayoutConstraint *contraint1 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:40.0];
//子view的左边缘离父view的左边缘40个像素
NSLayoutConstraint *contraint2 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:40.0];
//子view的下边缘离父view的下边缘40个像素
NSLayoutConstraint *contraint3 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-40.0];
//子view的右边缘离父view的右边缘40个像素
NSLayoutConstraint *contraint4 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-40.0];

//把约束添加到父视图上
NSArray *array = [NSArray arrayWithObjects:contraint1, contraint2, contraint3, contraint4, nil];
[self.view addConstraints:array];

示例二

子view在父view的中间,且子view长300,高200。

[self.view setBackgroundColor:[UIColor redColor]];

//创建子view
UIView *subView = [[UIView alloc] init];
[subView setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:subView];

//使用Auto Layout约束,禁止将Autoresizing Mask转换为约束
[subView setTranslatesAutoresizingMaskIntoConstraints:NO];

//layout 子view

//子view的中心横坐标等于父view的中心横坐标
NSLayoutConstraint *constrant1 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
//子view的中心纵坐标等于父view的中心纵坐标
NSLayoutConstraint *constrant2 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0];
//子view的宽度为300
NSLayoutConstraint *constrant3 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:300.0];
//子view的高度为200
NSLayoutConstraint *constrant4 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:200.0];

//把约束添加到父视图上
NSArray *array = [NSArray arrayWithObjects:constrant1, constrant2, constrant3, constrant4, nil];
[self.view addConstraints:array];

修改约束

  1. 储存约束 ,便于之后修改

  2. 在其父view的constraints数组中遍历查找。

     NSArray *constrains = self.view.constraints;
     for (NSLayoutConstraint* constraint in constrains) {
     	if (constraint.firstAttribute == NSLayoutAttributeTop) {
     		constraint.constant = 10;
     	}
     }
    

更新约束方法

setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。

layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点一般布局动画可以在更新布局后直接使用这个方法让动画生效。

layoutSubviews:系统重写布局。

setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始。

updateConstraintsIfNeeded:告知立刻更新约束。

updateConstraints:系统更新约束。


注意点

  1. 如果你用了AutoLayout 再修改Frame 会有什么效果 有没有什么不好的

    当旋转后,autolayout约束又生效后,手动修改的frame可能就会失效

  2. 动画

    如果你用了AutoLayout 那么做动画的时候 你就不要再操作 Frame bounds center 等position属性,因为这些动画都是临时的 下次的View 被 setNeedsUpdateConstraint 这些全都失效,但是其他的可动画属性(Animation Properties) 还是可以的 如 Color alpha等


参考链接

http://blog.csdn.net/he_jiabin/article/details/48677911

http://www.cnblogs.com/GarveyCalvin/p/4165151.html

http://www.jianshu.com/p/683fbcbfb705

原文地址:https://www.cnblogs.com/sunyanyan/p/5266711.html