visual format language (VFL)
Available Symbols
VFL uses a number of symbols to describe your layout:
- | superview
-
standard spacing (usually 8 points; value can be changed if it is the spacing to the edge of a superview)- == equal widths (can be omitted)
-
20-
non standard spacing (20 points)- <= less than or equal to
- >= greater than or equal to
- @250 priority of the constraint; can have any value between 0 and 1000
250 - low priority
750 - high priority
1000 - required priority
Example Format String
H:|-[icon(==iconDate)]-20-[iconLabel(120@250)]-20@750-[iconDate(>=50)]-|
- H: 表示水平方向
- |-[icon 表示 icon的左边距跟父视图的左边距间隔是标准的间隔
- ==iconDate 表示 iconDate的宽度等于iconDate的宽度
- ]-20-[iconLabel 表示 icon的右边缘跟iconLabel的左边缘距离20.
- [iconLabel(120@250)] 表示: iconLabel的宽度为120点,优先级为低。 如果跟其他约束有冲突,iconLabel的宽度可以不为120.
- -20@750- 表示: iconLabel的右边缘跟iconDate的左边缘的距离为20点,优先级为高。
- [iconDate(>=50)] 表示: iconDate的宽度大于或等于50.
- -| 表示: iconDate的右边缘距离superview的右边缘为标准距离.
例子:
UILabel *hint = [[UILabel alloc] init];
hint.text = @"label";
hint.backgroundColor = [UIColor grayColor];
[self.view addSubview:hint];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:@"button" forState:UIControlStateNormal];
[self.view addSubview:button];
//关闭 autoresizing
hint.translatesAutoresizingMaskIntoConstraints = NO;
NSMutableArray *tempConstraints = [[NSMutableArray alloc] init];
[tempConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topLayoutGuide]-0-[hint(==50)]"
options:0
metrics:nil
views:@{@"topLayoutGuide":self.topLayoutGuide,@"hint":hint}]];
[tempConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[hint(==200)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(hint)]];
[self.view addConstraints:tempConstraints];
//关闭 autoresizing
button.translatesAutoresizingMaskIntoConstraints = NO;
NSMutableArray *buttonConstraints = [[NSMutableArray alloc] init];
[buttonConstraints addObjectsFromArray:
//toplayoutGuide是一个标准线,代表着可以开始布局的视图顶部
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topLayoutGuide]-50-[button(==50)]"
options:0
metrics:0
views:@{@"button":button,@"topLayoutGuide":self.topLayoutGuide}]];
[buttonConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[button(==120)]"
options:0
metrics:0
views:@{@"button":button}]];
// visual format language 做不了水平居中,得额外添加约束代码
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:button
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0]];
[self.view addConstraints:buttonConstraints];
布局效果图:
NSLayoutFormatOptions
UIButton *goBack = [UIButton buttonWithType:UIButtonTypeCustom];
[goBack setTitle:@"后一页" forState:UIControlStateNormal];
[self.view addSubview:goBack];
UIButton *goForward = [UIButton buttonWithType:UIButtonTypeCustom];
[goForward setTitle:@"前一页" forState:UIControlStateNormal];
[self.view addSubview:goForward];
UIButton *refresh = [UIButton buttonWithType:UIButtonTypeCustom];
[refresh setTitle:@"刷新" forState:UIControlStateNormal];
[self.view addSubview:refresh];
goBack.translatesAutoresizingMaskIntoConstraints = NO;
NSMutableArray *goBackConstraints = [[NSMutableArray alloc] init];
[goBackConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:[goBack(30)]-20-[bottomLayoutGuide]"
options:0
metrics:nil
views:@{@"goBack":goBack,@"bottomLayoutGuide":self.bottomLayoutGuide}]];
[goBackConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-50-[goBack(60)]"
options:0
metrics:nil
views:@{@"goBack":goBack}]];
goForward.translatesAutoresizingMaskIntoConstraints = NO;
[goBackConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[goBack]-30-[goForward(60)]"
options:NSLayoutFormatAlignAllCenterY
metrics:nil
views:NSDictionaryOfVariableBindings(goBack,goForward)]];
refresh.translatesAutoresizingMaskIntoConstraints = NO;
[goBackConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[goForward]-30@250-[refresh]-50@750-|"
options:NSLayoutFormatAlignAllCenterY
metrics:nil
views:NSDictionaryOfVariableBindings(goForward,refresh)]];
[self.view addConstraints:goBackConstraints];
NSLayoutFormatAlignAllCenterY 表示跟其中一个关联的控件的 centerY的值一样(在VFL表达式中的元素,必须有一个的centerY值是确定的,这样才能确定其他元素的centerY的值)。 效果图如下:
其他值类推,例如有这样的:
constraintsWithVisualFormat:@"V:[Label1]-4-[Label2]",
//使得 Label1的左右边缘等于Label2的左右边缘。
options: [.alignAllLeading, .alignAllTrailing],
metrics: nil,
views: views]
前提是:label2的左右边缘都已经确定了,上面的VFL约束才能正确执行
@"H:|-15-[Label2]-15-|"
Metrics
Metrics其实就是定义 一些常量,或者变量。把常量名或者变量名应用到 VFL中。解析的时候,替换为相应的值。 例如:
[swift]
// MARK: - Constants
private let horizontalPadding: CGFloat = 15.0
let metrics = ["hp": horizontalPadding,
"iconImageViewWidth": 30.0]
let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-hp-[iconImageView(iconImageViewWidth)]-[appNameLabel]-[skipButton]-hp-|",
options: [.AlignAllCenterY],
metrics: metrics,
views: views)
let summaryHorizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-hp-[summaryLabel]-hp-|",
options: [],
metrics: metrics,
views: views)