目前发现项目里面很多控件位置控制都是用硬编码实现的。这样在后期维护起来非常困难,所以希望能够使用新的ios的自动布局控件
ios自带的布局空间如果用BI用起来还是非常方便的可以直接图像完成,不过项目里面全是手写代码。并且我也很赞同手写界面代码的方式。不过有一篇文章说的是可以各区所长。这种也是非常好的方式,比如MFC的写法就是界面和代码可以配合的很好。
界面实现自动布局
文章在这里点击打开链接
代码自动布局
代码实现有三个需要注意的地方
1对子视图的约束,若是基于父视图,要通过父视图去添加约束。
2对子视图进行自动布局调整,首先对UIView的一个属性设置,这是因为如果我们用Interface Builder,勾选Ues Autolayout,这时autoresizingMask就会被Auto Layout 取代,在手写代码时,我们就需要手动控制,代码如下 [_shadow setTranslatesAutoresizingMaskIntoConstraints:NO]
3在添加约束前,要先将子视图添加到父视图上。
1、使用Objective-C风格的方法创建约束对象
所谓Objective-C风格的方法,就是通过原生枚举和一些属性设置来创建NSLayoutConstraint对象。使用NSLayoutConstraint类的如下方法:
+(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:要约束的对象属性,这个就是一些枚举,如下:
typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
NSLayoutAttributeLeft = 1,//左
NSLayoutAttributeRight,//右
NSLayoutAttributeTop,//上
NSLayoutAttributeBottom,//下
NSLayoutAttributeLeading,//起始边,类似左,只在某些从右向左排列的语言中和NSLayoutAttributeLeft有大区别
NSLayoutAttributeTrailing,//结束边
NSLayoutAttributeWidth,//宽度
NSLayoutAttributeHeight,//高度
NSLayoutAttributeCenterX,//x中心
NSLayoutAttributeCenterY,//y中心
NSLayoutAttributeBaseline,//基线
NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline,
NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0),
//下面的属性是设置的边距 意义和上面类似 对应左,右等边距
NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
//无,后面会说应用场景
NSLayoutAttributeNotAnAttribute = 0
};
relation:约束的选项,对应<=,==,>=这些,枚举如下:
typedef NS_ENUM(NSInteger, NSLayoutRelation) {
NSLayoutRelationLessThanOrEqual = -1,//<=
NSLayoutRelationEqual = 0,//==
NSLayoutRelationGreaterThanOrEqual = 1,//>=
};
view2:与之对应添加约束的视图对象,例如,如过我要设置view1的上边距离父视图的上边一定间距,这个view2就是view1的父视图,如果我要设置view1与另一个视图一定距离,这个view2就是另一个视图。
attr2:view2的要约束的属性,和attr1含义一样。
multiplie:约束的比例,比如view1的宽是view2的宽的两倍,这个multiplie就是2.
C:这是具体的约束值
对于这些属性,文档上有这样的解释:view1.attr1 = view2.attr2 * multiplier + constant
例如,我们创建一个label,将它的宽高固定为100*100,位置放在屏幕的中央,我们可以使用如下的约束代码:
UILabel * label = [[UILabel alloc]init];
label.numberOfLines = 0;
//使用代码布局 需要将这个属性设置为NO
label.translatesAutoresizingMaskIntoConstraints = NO;
label.backgroundColor = [UIColor redColor];
//创建x居中的约束
NSLayoutConstraint * constraintx = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
//创建y居中的约束
NSLayoutConstraint * constrainty = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
//创建宽度约束
NSLayoutConstraint * constraintw = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100];
//创建高度约束
NSLayoutConstraint * constrainth = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100];
//添加约束之前,必须将视图加在父视图上
[self.view addSubview:label];
[self.view addConstraints:@[constraintx,constrainty,constrainth,constraintw]];
什么是VFL语言
VFL(Visual Format Language),“可视化格式语言”。
VFL是苹果公司为了简化autolayout的编码而推出的抽象语言。
语法说明
复制代码
H:[cancelButton(72)]-12-[acceptButton(50)]
cancelButton宽72,acceptButton宽50,它们之间间距12
H:[wideView(>=60@700)]
wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束条件越先被满足)
V:[redBox][yellowBox(==redBox)]
垂直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox
H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
水平方向上,Find距离父view左边缘间隔10,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边边缘的间距都是默认宽度。(竖线“|”表示superview的边缘)。
复制代码
使用方法
复制代码
使用VFL来创建约束数组
+(NSArray )constraintsWithVisualFormat:(NSString )format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary )metrics views:(NSDictionary )views;
format:VFL语句
opts:约束类型
metrics:VFL语句中用到的具体数值
views:VFL语句中用到的控件
创建一个字典(内部包含VFL语句中用到的控件)的快捷宏定义
NSDictionaryOfVariableBindings(…)
复制代码
实例展示
效果图如下:
实现代码:
复制代码
-(void)horizontalLayout{
//1.添加两个控件
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
blueView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:blueView];
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
redView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:redView];
//2.添加约束
//2.1水平方向的约束
NSString *hVFL = @"H:|-30-[blueView]-30-[redView(==blueView)]-30-|";
NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:hVFL options:NSLayoutFormatAlignAllBottom | NSLayoutFormatAlignAllTop metrics:nil views:@{@"blueView":blueView, @"redView":redView}];
[self.view addConstraints:hCons];
//2.2垂直方向的约束
NSString *vVFL = @"V:[blueView(50)]-30-|";
NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:vVFL options:0 metrics:nil views:@{@"blueView":blueView}];
[self.view addConstraints:vCons];
}
-(void)verticalLayout{
//1.添加两个控件
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
blueView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:blueView];
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
redView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:redView];
//2.添加约束
//2.1水平方向的约束
NSString *hVFL = @"H:|-30-[blueView]-30-|";
NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:hVFL options:0 metrics:nil views:@{@"blueView":blueView}];
[self.view addConstraints:hCons];
//2.2垂直方向的约束
NSString *vVFL = @"V:|-30-[blueView(50)]-30-[redView(==blueView)]";
NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:vVFL options:NSLayoutFormatAlignAllRight metrics:nil views:@{@"blueView":blueView, @"redView":redView}];
[self.view addConstraints:vCons];
NSLayoutConstraint *redLeftCon = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
[self.view addConstraint:redLeftCon];
}
复制代码
小结
最后对格式的字符串作一个总结介绍:
功能 | 表达式 |
---|---|
水平方向 | H: |
垂直方向 | V: |
Views | [view] |
SuperView | | |
关系 | >=,==,<= |
空间,间隙 | - |
优先级 | @value |