Autolayout + VFL(Visual Format Language)

最近在学习iOS的布局,在storyboard里,确定布局的思路:

1、确定能确定的;

2、无法确定的,看看是否可以想办法和其他控件关联起来,再根据关系来确定能确定的位置.

例子:实现如下图的布局

过程:

1、确定能确定的;

左上角的View,左边和上边距离父view的距离都是0(当然,这里假设了view的宽度和高度都是100)

设置完成后,点击Add 4 Constraints即可,现在界面如下所示;

左边View Controller Scene后面有个黄色图标,该图标的意思是警告的意思,是最终的位置和目前位置不匹配,更新一下即可,效果如下:

其他3个的设置过程大概也是一样,不一一设置了.

2、无法确定的,看看是否可以想办法和其他控件关联起来,再根据关系来确定能确定的位置.

例子效果图:

效果图中的两个view的高度和宽度永远相等(这里我设置高度为50),距离父view左边、右边、下边间距和2个view之间的间距相等.都是30.

这种效果可以确定的是红色view离父view的左边和底部的位置都是固定的,都为30,设置如:

这里要注意的是设置底部时要注意距离的是父view还是Bottom Layout Guide了,当然顶部也是需要注意的。(其实就是需要注意参照物)

在这里,会发现设置完后左上角会有个红色的图标,这说明还有位置没有设置约束或者有约束冲突。

蓝色view离父view的右边和底部的位置都是固定的,也是30:

那么现在问题来了,只确定这2个位置,是无法给这两个view来确定最终位置的。

在这里,由于两个view的宽度都是相等的,而且间距也是固定了,那么是否就可以最终固定下这两个view的位置了呢?

先选中两个view,然后设置宽度相等:

接着选中任意一个view,设置间距,这里我选择的是红色的view来设置的

然后更新下frame即可:

可以选择选中的view,也可以选择所有的,点击Update Frames后,最终结果如下图:

以上为在storyboard里使用Autolayout来布局的一些过程,其他的也差不多,就不一一讲述了。

使用代码的形式:

在添加时唯一要注意的是添加的目标view要遵循以下规则:

  • 对于两个同层级view之间的约束关系,添加到他们的父view上

 

  • 对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上

 

  • 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上


实现Autolayout的步骤
利用NSLayoutConstraint类创建具体的约束对象
添加约束对象到相应的view上

- (void)addConstraint:(NSLayoutConstraint *)constraint;

- (void)addConstraints:(NSArray *)constraints;

代码实现Autolayout的注意点
要先禁止autoresizing功能,设置view的下面属性为NO
view.translatesAutoresizingMaskIntoConstraints = NO;
 
添加约束之前,一定要保证相关控件都已经在各自的父控件上
不用再给view设置frame
 
一个NSLayoutConstraint对象就代表一个约束
创建约束对象的常用方法
1 +(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
view1 :要约束的控件
attr1 :约束的类型(做怎样的约束)
relation :与参照控件之间的关系
view2 :参照的控件
attr2 :约束的类型(做怎样的约束)
multiplier :乘数
c :常量
自动布局有个核心公式

obj1.property1 =(obj2.property2 * multiplier)+ constant value

上面第二个效果图的代码写法如下:

 1  //添加一个红色view
 2     UIView *redView = [[UIView alloc] init];
 3     redView.backgroundColor = [UIColor redColor];
 4     redView.translatesAutoresizingMaskIntoConstraints = NO;
 5     [self.view addSubview:redView];
 6     
 7     
 8     //添加一个蓝色view
 9     UIView *blueView = [[UIView alloc] init];
10     blueView.backgroundColor = [UIColor blueColor];
11     blueView.translatesAutoresizingMaskIntoConstraints = NO;
12     [self.view addSubview:blueView];
13     
14     //给红色view添加约束
15     NSLayoutConstraint *redLeft = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:30.0];
16     [self.view addConstraint:redLeft];
17     
18     NSLayoutConstraint *redBottom = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-30.0];
19     [self.view addConstraint:redBottom];
20     
21     NSLayoutConstraint *redHeight = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:0.0 constant:50.0];
22     [redView addConstraint:redHeight];
23     
24     //给蓝色view添加约束
25     NSLayoutConstraint *blueRight = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-30.0];
26     [self.view addConstraint:blueRight];
27     
28     NSLayoutConstraint *blueBottom = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-30.0];
29     [self.view addConstraint:blueBottom];
30     
31     NSLayoutConstraint *blueHeight = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:0.0 constant:50.0];
32     [blueView addConstraint:blueHeight];
33     
34     NSLayoutConstraint *blueWidth = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0];
35     [self.view addConstraint:blueWidth];
36     
37     NSLayoutConstraint *blueLeft = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeRight multiplier:1.0 constant:30.0];
38     [self.view addConstraint:blueLeft];

 看完使用代码来自动布局是不是有种坑爹的感觉,好长好臭~~别急,苹果还给我们提供了另外一种方式VFL:

什么是VFL?
VFL全称是Visual Format Language,翻译过来是“可视化格式语言”
VFL是苹果公司为了简化Autolayout的编码而推出的抽象语言:
VFL示例:
H:[cancelButton(72)]-12-[acceptButton(50)]
canelButton宽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左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线“|” 表示superview的边缘)

VFL的使用:

使用VFL来创建约束数组

+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;

format :VFL语句
opts :约束类型
metrics :VFL语句中用到的具体数值
views :VFL语句中用到的控件
 
上面第二个效果图的VFL代码的写法如下:
 1     //初始化两个view
 2     UIView *redView = [[UIView alloc] init];
 3     redView.backgroundColor = [UIColor redColor];
 4     redView.translatesAutoresizingMaskIntoConstraints = NO;
 5     [self.view addSubview:redView];
 6     
 7     UIView *blueView = [[UIView alloc] init];
 8     blueView.backgroundColor = [UIColor blueColor];
 9     blueView.translatesAutoresizingMaskIntoConstraints = NO;
10     [self.view addSubview:blueView];
11 
12     //设置水平方向上的约束,代表的意思是blueView离父view左边间距为30,和redView的间距为30,redView和父view的右间距为30,redView的宽度和blueView的宽度相等
13     NSString *hVFL = @"H:|-30-[blueView]-30-[redView(==blueView)]-30-|";
14     NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:hVFL options:NSLayoutFormatAlignAllBottom | NSLayoutFormatAlignAllTop metrics:nil views:@{@"blueView":blueView,@"redView":redView}];
15     [self.view addConstraints:hCons];
16     
17     //设置垂直方向上的约束,代表的意思是blueView的高度是50,离父view的底部间距是30
18     NSString *vVFL = @"V:[blueView(50)]-30-|";//@"V:-30-[blueView(50)]",这里的30代表离父类的顶部间距是30
19     NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:vVFL options:0 metrics:nil views:@{@"blueView":blueView}];
20     [self.view addConstraints:vCons];

还是附上效果图吧:

原文地址:https://www.cnblogs.com/xiaomoge/p/4279245.html