//Create a left-aligned vertical column of view1 followed by view2, leaving an 8-point spacer between the two views.
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view1]-8-[view2]"
options:NSLayoutFormatAlignAllLeading
metrics:nil
views:NSDictionaryOfVariableBindings(view1, view2)]];
Here are a few things to note about how this constraints formatting example is created这里有几点需要注意怎样约束格式设置例子:
The axis (or orientation, if you’re using OS X) is specified first as a prefix, either H: or V:. When you omit the axis, the constraint defaults to horizontal layout. I encourage you to always use a prefix. Mandatory prefixes provide a consistent indication of design intent, ensuring that any missing prefix is guaranteed to be a mistake.(H: or V:表示水平和竖直布局,如果没有前缀默认的是水平布局,但是鼓励使用前缀)
Variable names for each view appear in square brackets (for example, [view1]).变量名是在中括号里出现。
The order of the view names in the string matches the requested order of the views in the layout. The order is normally from top to bottom or left to right. In Arabic and Hebrew locales, the order is right to left. You can also override the order with layout format options.(在字符串里view names的排列是从上到下从左到右的,但在阿拉伯语和现代以色列语它们是从右到左排列的。)
The fixed spacing appears between the two views as a number constant, -8-. Hyphens surround the number.两个views之间固定的距离是8。
The options parameter specifies alignment. In this example, it sets a leading alignment, which is left-aligned for English-like languages and right-aligned for languages like Arabic and Hebrew. Leading refers to the first horizontal edge encountered for the standard writing direction of the prevailing locale. Trailing refers to the final horizontal edge.options参数指定对齐方式,在这个例子里它设置的leading alignment,这是类似英语的语言的左对齐和阿拉伯语及现代以色列语的右对齐。Leading是指当前区域设置的标准的第一水平边缘, Trailing指的是最终的水平边缘。
A metrics dictionary parameter is not included in this example. When used, this parameter supplies constant numbers for value substitutions in constraints. For example, if you want to vary the spacing between these two views, you could replace 8 with a metric name like myOffset and assign that metric’s value via a dictionary.metrics参数在上面的例子中没有用到,这个参数把指定在约束中的值替换为常数。例如你想要改变两个views的距离,你可以使用像“myOffset”的metric name来代替8并且分配metric的值通过dictionary。
The views: parameter does not, despite its name, pass an array of views. It passes a dictionary of variable bindings. This dictionary associates variable name strings (for example, "view1") with the objects they represent (the view instance whose variable name is view1). This indirection allows you to use developer-meaningful symbols like "nameLabel" and "requestButton" in your format strings.
Here are the two constraints for this example上面的例子相当于两个约束:
[NSLayoutConstraint constraintWithItem:view2
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:view1
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:8.0];
[NSLayoutConstraintconstraintWithItem:view1
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:view2
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0.0];
Table 4-1 lists the options you can supply to the visual format method. These options include alignment masks (left column) and formatting directions (right column). You can supply only one format direction. Prior to iOS 7, Apple also required that you choose only one alignment mask at a time. That requirement is now gone. To combine options, you use a bitwise OR.
1.Alignment
You should always apply alignment masks perpendicular to your format. When you create a horizontal row, you specify a vertical alignment (and vice versa). For example, imagine laying out a row of objects from left to right—for example, H:[view1]-[view2]-[view3]-[view4]. You can align their tops, their middles, or their bottoms simply by tweaking them up or down a bit. However, you can’t align their lefts or rights because doing so would force them out of the layout order you specified. All the views would have to scoot left or scoot right, essentially contradicting the visual format.
2.Skipping Options
You skip options by supplying 0 to the options parameter. NSLayoutConstraint builds constraints from the visual format you supply but doesn’t add any alignment constraints:
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view1]-8-[view2]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(view1, view2)]];
When you’re working with visual constraints, the layout system associates name strings like “view1” and “view2” with the objects they represent. Variable bindings build these associa- tions. You create them by calling NSDictionaryOfVariableBindings(), a macro defined in NSLayoutConstraint.h. You pass the macro an arbitrary number of local view variables, as in this example:(当你正在处理visual constraints时,layout系统将像“view1” “view2”的name string与它们所代表的对象相关联)
NSDictionaryOfVariableBindings(view1, view2, view3, view4)
As you see, this macro doesn’t require a nil semaphore to terminate your list. It builds a dictionary from the passed variables, using the variable names as keys and the objects they point to as values.就像你所看到的,macro不需要一个nil信号来终止你的list。它从传递的变量生成一个dictionary,使用变量名作为keys,使用对象指针作为values。
For example, this call:
NSDictionaryOfVariableBindings(leftLabel, rightLabel)
builds this dictionary:
@{@"leftLabel":leftLabel, @"rightLabel":rightLabel}.
When you don’t know a constant’s value a priori, a metrics dictionary supplies that value to your visual format string.当你事先不知道一个常量的值时, metrics dictionary 提供你的visual format string值。
For example, consider this:
@"V:[view1]-spacing-[view2]"
Here, the word spacing represents some spacing value, which has not yet been determined. You pass that value by building a dictionary that equates the word string with its value. For example, this dictionary associates spacing with the number 10:
NSDictionary *metrics = @{@"spacing":@10};
You supply this dictionary to the metrics parameter of the visual format creation method:
[NSLayoutConstraint
constraintsWithVisualFormat:@"V:[view1]-spacing-[view2]"
options:NSLayoutFormatAlignAllCenterX
metrics:metrics
views:bindings];
NSLayoutConstraint uses the metrics dictionary to substitute the value 10 for the spacing string. Unlike the bindings dictionary, which equates views to names, the metrics dictionary supplies numbers.(NSLayoutConstraint使用metrics dictionar来代替间距字符串的值10.不像bindings dictionary与views名称一样,metrics dictionary提供数字)
- (void) constrainView: (VIEW_CLASS *) view toWidth: (CGFloat) width
{
NSString *formatString = @"H:[view(==width)]";
NSDictionary *bindings = NSDictionaryOfVariableBindings(view); NSDictionary *metrics = @{@"width":@(width)};
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:formatString
options:0
metrics:metrics
views:bindings];
[view addConstraints:constraints];
}
Superviews
You do not need to name the superview in your bindings dictionary. Auto Layout understands that | refers to the view’s superview. Typical cases for using the superview character include the following:(在你的bindings dictionary里你不需要知道superview的名字,Auto Layout的理解是“|”指该视图的superview。典型情况使用superview character包括下面的内容)
Stretching a view to fit its superview—for example, "H:|[view]|"
Offsetting a view from its superview’s edge—for example, "V:[view]-8-|"
Creating a superview-aligned row or column of views—for example, "V:|-[view1]-[view2]-[view3]-[view4]"
Connections specify inter-view spacing. Listed between each view (including superview refer- ences), they mark out the distance to add.
Empty Connections: H:[view1][view2] or V:|[view3]
Standard Spacers:A hyphen (-) represents a standard fixed space. The constraint "H:|-[view1]-[view2]" leaves a small gap between View 1 and View 2 and between View 1 and its superview . Although officially undocumented, this standard is generally 8 points for view-to-view layout and 20 points for view-to-superview layout.
Numeric Spacers:A numeric constant placed between hyphens sets an exact gap size. The constraint "H:[view1]-30-[view2]" adds a 30-point gap between the two views.
The following rules all have two views that abut one another:
You prioritize layout requests by adding an optional value to the format string. Append any connection or sizing rule with an @ sign followed by the numeric priority you want to assign. For example, in this visual format:
//优先级为20
"H:|-(5@20)-[view1]-[view2]-|"
The visual constraint formatting language optionally specifies view sizing within the square brackets that otherwise delimit the view name. You add the sizing specifications in parentheses after the name, (visual constraint formatting language指定在方括号内以区分view name,在name后面添加尺寸规格)like this:
You might specify a view with a fixed 120-point width: @"H:[view1(120)]". If you prefer to state the relation explicitly, you can add that as well: @"H:[view1(==120)]".
You might specify that the width of a view is at least 50 points, using the following format: @"H:[view1(>=50)]". A similar approach lets a view’s size range between 50 and 70 points. As with spacing, separate your rules with commas for compound items: "H:[view1(>=50,<=70)]".
You can refer to other views in sizing requests. For example, this format matches View 1’s width to View 2’s width: "H:[view1(view2)]". If you add size matching to the "H:|-[view1]-[view2]-|" format originally shown in Figure 4-6, you ensure that both subviews are the same size, fixing the lopsided random layout (that is, "H:|- [view1(view2)]-[view2]-|").
Not all views need to participate in size matching. The next request creates matching flanking views around a primary view while stretching all three views across the superview: @"H:|-[view1(<=80)]-[view2]-[view3(view1)]-|". The format limits View 1’s size to 80 points and matches it to View 3, ensuring that View 2 stretches to occupy the remaining space. Figure 4-10 shows the resulting layout.
View sizes can also express priorities. In the format string "H:|-[view1(==250@700)]- [view2(==250@701)]-|", both View 1 and View 2 request to be 250 points wide. View 2 wins (see Figure 4-11) because its request has a higher priority.
Although you can easily produce constraints in code that express relative size using multipliers, you cannot do so in visual constraints. This is an illegal constraint: "H:|- [view1(==2*view2)]-[view2]-|". If you want to say “View 1 is twice the width of View 2,” you need to do so in code.
void constrainViewSize(UIView *view, CGSize size, NSUInteger priority)
{
NSDictionary *bindings =
NSDictionaryOfVariableBindings(view);
NSDictionary *metrics = @{@"width":@(size.width), @"height":@(size.height), @"priority":@(priority)};
for (NSString *formatString in @[ @"H:[view(==width@priority)]", @"V:[view(==height@priority)]", ])
{
NSArray *constraints = [NSLayoutConstraint
constraintsWithVisualFormat:formatString
options:0 metrics:metrics views:bindings];
[view addConstraints:constraints];
}
}