需求
AutoLayout给我的感觉就是充分利用了布局的相对性:对于一个新添加的控件(item1),我们要在界面中确定它的位置,但是需要保证他和其他控件(item2)保持一定的关系,比如item1一定要在item2上边20个像素点的位置,或者item1的宽度是item2的一半。通过
[item1 setFrame:CGRectMake(x,y,width,height)]
可以确定item1的相对于屏幕原点的位置,也可以手动调整大小使其尺寸满足条件,但是如果item2的位置或者尺寸变化的时候,所有和item2存在相对位置关系的item都要重新setFrame,这是显然不可取的。
虽然好多项目中,当前控件需要依赖其他控件改变位置时,我都是通过计算好尺寸之间的依赖关系,从而实现“牵一发而动全身”的效果。
在storyboard中可以drag完各种空间之后,然后设置各种Constraints,相对布局也就设置好了,但是如果不用故事版,用代码怎样实现这样的功能——NSLayoutContraint。
使用方法
- 对要使用相对布局的空间设置
setTranslatesAutoresizingMaskIntoConstraints为NO; - 声明NSLayoutContraint对象;
- 对这个对象添加布局设置;
- 将这个对象添加到所有关联控件的公共父view中。
在进行上述过程之前,要确保已经将item添加到superview中了
[super.view addSubview :item1];
不然会crash,亲测!
例子
针对上述流程,分别给出例子
前提条件
[ item1 setTranslatesAutoresizingMaskIntoConstraints:NO];声明NSLayoutContraint的对象
对这个对象添加布局设置
1
2
3
4
5
6NSLayoutConstraint *atrributeBottom = [NSLayoutConstraint constraintWithItem:item1
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:item2
attribute:NSLayoutAttributeTop
multiplier:1.0constant:-20];如果这个item1和item2是self.view的subview,则将这个对象添加到所有关联控件的公共父view中:
[self.viewaddConstraint : atrributeBottom ];
这样就满足了上文中提到的“item1一定要在item2上边20个像素点的位置”。
图示如下:
说明
item1为待安放的控件,item2为参考控件,这条添加属性的语句第一行,指出控件以及该控件本次需要设定的属性,即 item1.NSLayoutAttributeBottom ,第二行相关语句和作用相同,即item2.NSLayoutAttributeTop,指出这次要确定的相对关系是,item1的底边与item2的顶边。
那么他们具体是什么关系呢?就是由related,mutiplier,constant决定的了,按照公式:
item1.attribute = multiplier * item.attribute + constant
同样,如果想让item1的宽度是item2的一半多5,则有1
2
3
4
5
6NSLayoutConstraint *item1Width =[NSLayoutConstraint constraintWithItem:item1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:item2
attribute:NSLayoutAttributeWidth
multiplier:0.5 constant:5];
另外,再补充一点,如果我们想确定的属性不需要任何想item2的参照物,比如固定item1的宽度就是80,那么只把参照物item2设置为nil就好:1
2
3
4
5
6
7
8NSLayoutConstraint *item1Width =[NSLayoutConstraint
constraintWithItem:item1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:80];
即 item1.NSLayoutAttributeWidth = constant
注意
- multiplier不能为0;
- 可以把全部属性设置完成后,调用方法
[self addConstraints: @[atrributeBottom,item1Width] ];
将所有Constraint属性一起加入到控件中。当然也可以单独添加,选用的方法不同而已; - 一定要保证此前已经将控件添加到公共的superView中了。
done!