iOS Programming  Auto Layout: Programmatic Constraints 

1. 

However, if your views are created in code, then you will need to constrain them programmatically.

如果你的view是由代码创建的,那么你需要用编程限制它了。

To have a view to work with, you are going to recreate the image view programmatically and then constrain it in the UIViewController method viewDidLoad. This method will be called after the NIB file for BNRDetailViewController's interface has been loaded.

viewDidLoad方法将会被调用在NIB文件被加载后。

If you are creating and constraining an entire view hierarchy, then you override loadView.

如果你要创建和constraining 整个view hierarchy ,你需要重写loadView。

If you are creating and constraining an additional view to add to a view hierarchy that was created by loading a NIB file, then you override viewDidLoad instead.

如果你creating 和constraining 一个另外的view并加入一个由NIB文件加载的view hierarchy,你需要重写viewDidLoad.

 
 

In BNRDetailViewController.m, implement viewDidLoad to create an instance of UIImageView.

 
 

- (void)viewDidLoad

{
[super viewDidLoad];

UIImageView *iv = [[UIImageView alloc] initWithImage:nil];

// The contentMode of the image view in the XIB was Aspect Fit: iv.contentMode = UIViewContentModeScaleAspectFit;

// Do not produce a translated constraint for this view iv.translatesAutoresizingMaskIntoConstraints = NO;

// The image view was a subview of the view [self.view addSubview:iv];

// The image view was pointed to by the imageView property

self.imageView = iv; }

 
 

The line of code regarding translating constraints has to do with an older system for scaling interfaces – autoresizing masks.

考虑到translating constraints 与scaling interface -autoresizing masks 有关。

Every view has an autoresizing mask. By default, iOS creates constraints that match the autoresizing mask and adds them to the view.

每个view都有一个autoresizing mask. 默认情况下,iOS 创建constraints 匹配autoresizing mask 并把他们添加到view上。

These translated constraints will often conflict with explicit constraints in the layout and cause an unsatisfiable constraints problem. The fix is to turn off this default translation by setting the property translatesAutoresizingMaskIntoConstraints to NO.

这些translated constraints 会语我们明确指出的constraints 并导致unsatisfiable constraints problem.修复的办法是通过设置translatesAutoresizingMaskIntoConstraints为NO来关闭default translation.

The UIImageView should span the entire width of the screen and should maintain the standard 8 point spacing between itself and the dateLabel above and the toolbar below. Here are the constraints for the image view spelled out:

(1)left edge is 0 points from the image view's container 

(2)right edge is 0 points from the image view's container

(3) top edge is 8 points from the date label
(4)bottom edge is 8 points from the toolbar

Apple recommends using a special syntax called Visual Format Language (VFL) to create constraints programmatically.

苹果推荐使用一个专门的syntax 叫做Visual format language(VFL)来创建constraints programmatically.

This is how you will constrain the image view. However, there are times when a constraint cannot be described using VFL.n those cases, you must take another approach.

2. Visual formate language 

Visual Format Language is a way of describing constraints in a literal string.

它是一种literal string 来描述constraints.

You can describe multiple constraints in one visual format string.

A single visual format string, however, cannot describe both vertical and horizontal constraints.

一个visual format string不能表述既有vertical又有horizontal的constraints.

Thus, for the image view, you are going to come up with two visual format strings: one that constrains the horizontal spacing of the image view and one that constrains its vertical spacing.

Here is how you would describe the horizontal spacing constraints for the image view as a visual format string:

这个就是你怎样用visual format string 表述horizontal spacing constrictions :

@"H:|-0-[imageView]-0-|"

The H: specifies that these constraints refer to horizontal spacing. The view is identified inside square brackets.

H 表明这个限制指向的是水平。这个view的identifier被方括号包围。

The pipe character (|) stands for the view's container.

| 代表了view的container。

This image view, then, will be 0 points away from its container on its left and right edges.

这个image view 将会是离它的container 的左侧和右侧边0points。

When the number of points between the view and its container (or some other view) is 0, the dashes and the 0 can be left out of the string:

@"H:|[imageView]|"

如果是0的话还可以简写成以上。

The string for the vertical constraints looks like this:

vertical constraints 的string 像这样:

@"V:[dateLabel]-8-[imageView]-8-[toolbar]"

 
 

Notice that "top" and "bottom" are mapped to "left" and "right", respectively, in this necessarily horizontal display of vertical spacing. The image view is 8 points from the date label at its top edge and 8 points from the toolbar at its bottom edge.

You could write this same string like this: 你也可以写成这样:

@"V:[dateLabel]-[imageView]-[toolbar]"

The dash by itself sets the spacing to the standard number of points between views, which is 8.

dash 被它自己设置spacing 为标准的number of points 在两个view 间,就是8.

 
 

Imagine you had two image views with the following horizontal constraints:

考虑你有两个view在水平的constraints:

(1)the horizontal spacing between the image views should be 10 points

两个image view 的水平spacing应该是10 points。

(2)the lefthand image view's left edge should be 20 points from its superview

 
 

(3)the righthand image view's right edge should be 20 points from its superview

You could describe the three constraints in one visual format string:

@"H:|-20-[imageViewLeft]-10-[imageViewRight]-20-|"

The syntax for a fixed size constraint is simply adding an equality operator and a value in parentheses inside a view's visual format:

这个syntax为一个fixed size constraint 是简单地添加一个equality operator 和一个在括号里地值在一个view 的visual format:

@"V:[someView(==50)]"

This view's height would be constrained to 50 points.

3. Creating Constraints  创建 constraints

A constraint is an instance of the class NSLayoutConstraint. When creating constraints programmatically, you explicitly create one or more instances of NSLayoutConstraint and then add them to the appropriate view object.

 constraint 是NSLayoutConstraint的一个实例。当你创建一个 constraints programmatically,你明确地创建了一个或多个NSLayoutConstraint实例,并把它们添加到对应的view object上。

Creating and adding constraints is one step when working with a XIB, but it is always two distinct steps in code.

creating and add constraints 是一步当用XIB时,但是在code里就是两步:

You create constraints from a visual format string using the NSLayoutConstraint method:

+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts

metrics:(NSDictionary *)metrics views:(NSDictionary *)views

This method returns an array of NSLayoutConstraint objects because a visual format string typically creates more than one constraint.

这个方法返回一列NSLayoutConstraint对象因为 visual format string一般都是创建多余一个的constraint.

The first argument is the visual format string. For now, you can ignore the next two arguments, but the fourth is critical.

The fourth argument is an NSDictionary that maps the names in the visual format string to view objects in the view hierarchy.

第四个参数是在visual format string 的名字到在view hierarchy 中的view 对象的名字的一个map。

The two visual format strings that you will use to constrain the image view refer to view objects by the names of the variables that point to them.

@"H:|-[imageView]-|" @"V:[dateLabel]-[imageView]-[toolbar]"

However, a visual format string is just a string, so putting the name of a variable inside it means nothing unless you explicitly make the association.

把变量的名字放进format string在你指明了他们的关系之前是毫无意义的。

In BNRDetailViewController.m, create a dictionary of names for the views at the end of viewDidLoad.

    NSDictionary *nameDictionary=@{@"imageView": self.imageView,@"dateLabel":self.dateLabel,@"toolBar":self.toolbar};

You are using the names of your variables as keys, but you can use any key to name a view. The only exception is the | character, which is a reserved name for the superview (container) of the views being referenced in the string.

你可以用任意的关键字命名一个view。

Next, in BNRDetailViewController.m, create the horizontal and vertical constraints for the image view:

 
 

// imageView is 0 pts from superview at left and right edges

 views:nameDictionary];

// imageView is 8 pts from dateLabel at its top edge... // ... and 8 pts from toolbar at its bottom edge NSArray *verticalConstraints =

 metrics:nil views:nameDictionary];

4.Adding constraints 

You now have two arrays of NSLayoutConstraint objects. However, these constraints will have no effect on the layout until you explicitly add them using the UIView method

你已经有两组NSLayoutConstraints objects.但是如果你不明确地用UIView 方法把他们加进去,这些constraints是没有用得。

- (void)addConstraints:(NSArray *)constraints

Which view should receive the addConstraints: message?

什么时候view应该接受addConstraints消息?

Usually, the closest common ancestor of the views that are affected by the constraint.

一般是受constraint影响离最近的view公共的祖先。

Here is a list of rules you can follow to determine which view you should add constraints to:

下面是一些你往哪个view添加这些constraints的一些规则:

(1)If a constraint affects two views that have the same superview (such as the constraint labeled "A" in Figure 16.1), then the constraint should be added to their superview.

如果constraint影响有公共superview的两个view,那么constraint应该添加到它们的superview上。
(2)If a constraint affects just one view (the constraint labeled "B"), then the constraint should be added to the view being affected.

如果一个constraint仅仅影响一个view,那么这个constraint应该加在被影响的view上。

(3)If a constraint affects two views that do not have the same superview but do share a common ancestor much higher up on the view hierarchy (the constraint labeled "C"), then the first common ancestor gets the constraint.

如果一个限制影响的两个view,并没有共同的super view,而他们有共同的祖先,在view hierarchy中,那么应该加在他们的一个共同的祖先上。
(4)If a constraint affects a view and its superview (the constraint labeled "D"), then this constraint will be added to the superview.

如果一个祖先即影响了view及view 的superview,那么应该加在sup view上。

For the image view's horizontal constraints, this determination is easy. These constraints affect only the imageView and its superview, so you add them to the superview – the view of the BNRDetailViewController.

For the vertical constraints, the imageView, dateLabel, and toolbar are the affected views. They all share the same superview (the view of the BNRDetailViewController), so you also add these constraints to the superview.

In BNRDetailViewController.m, add both sets of constraints to the BNRDetailViewController's view at the end of viewDidLoad.

 
 

    [self.view addConstraints:horizontalConstraints];

    [self.view addConstraints:verticalConstraints];

5 Intrinsic Content Size

content size的本质

Intrinsic content size is information that a view has about how big it should be based on what it displays.

Intrinsic content size是一个view根据它要显示的大约应该多大的信息。

For example, a label's intrinsic content size is based on how much text it is displaying. In your case, the image view's intrinsic content size is the size of the image that you selected.

例如:label's intrinsic content size 根据它有多少文字要显示,而image view 的intrinsic content size 是你要选择的image 的size。

Auto Layout takes this information into consideration by creating intrinsic content size constraints for each view.

Auto Layout通过考虑这些信息通过为每个view创建 intrinsic content size constraints 

Unlike other constraints, these constraints have two priorities: a content hugging priority and a content compression resistance priority.

不同于其他的限制,这些限制有两个priorities:content hugging  priority和content compression resistence priority.

(1)Content hugging priority:tells Auto Layout how important it is that the view's size stay close to, or "hug", its intrinsic content. A value of 1000 means that the view should never be allowed to grow larger than its intrinsic content size. If the value is less than 1000, then Auto Layout may increase the view's size when necessary.

告诉auto layout 这个view's size 靠近或者hug 它的instrinsic content 是有多重要。1000代表这个view应该不允许比它的intrinsic content size 大。如果这个值小于1000,那么auto layout 应该根据当需要的时候增加view 的尺寸。

(2)content compression resistance priority :tells Auto Layout how important it is that the view avoid shrinking, or "resist compressing", its intrinsic content. A value of 1000 means that the view should never

be allowed to be smaller than its intrinsic content size. If the value is less than 1000, then Auto Layout may shrink the view when necessary.

告诉auto layout view 避免shrinking 或者抵制 compression ,它的intrinsic content 是有多重要。1000 意味着这个view永远不允许比它的intrinsic content size.如果小于1000,auto layout 应该允许缩小view 当需要的时候。

In addition, both priorities have separate horizontal and vertical values so that you can set different priorities for a view's height and width.

另外,两个priorities 都分别有 horizontal and vertical values所以你能为每个view的height and width 设置不同的优先级。

This makes a total of four intrinsic content size priority values per view.

这样每个view 都有四个intrinsic content size priority.

You can see and edit these values in Interface Builder. Reopen BNRDetailViewController.xib. Shift-click to select all three text fields in the canvas. Head to the inspector and select the tab to reveal the size inspector. Find the Content Hugging Priority and Content Compression Resistance

 Priority sections.

First, notice that these values are not 1000 and thus will never conflict with the constraints that you have added so far.This is why the layout will appear incorrectly with smaller-sized images.

注意到这些值都不是1000,因此与现在添加的constraints 并不冲突。这也是你的layout 当有smaller-sized 的图像时,并没有正确地原因

The value text field's content hugging vertical property is 250, which is lower than that of the image view (which is 251), so when faced with a small image, Auto Layout chooses to make the text field taller than its intrinsic content size.

It would be better if the image view had a smaller vertical content hugging and commpression resistance priority than the other subviews.

如果image view 有一个更小得vertical content hugging 和compression resistance priority 比其他的subview。

 
 

Open BNRDetailViewController.m and update viewDidLoad to lower these priorities.

 
 

// Set the vertical priorities to be less than
// those of the other subviews

 forAxis:UILayoutConstraintAxisVertical];

    [self.imageView setContentCompressionResistancePriority:700 forAxis:UILayoutConstraintAxisVertical];

 
 

6. The Other Way

There are times when a constraint cannot be created with a visual format string.

有些情况下,一个constraint 可能不能通过visual  format string 创建。

For instance, you cannot use VFL to create a constraint based on a ratio, like if you wanted the date label to be twice as tall as the name label or if you wanted the image view to always be 1.5 times as wide as it is tall.

 
 

you can create an instance of NSLayoutConstraint using the method

这样你可以通过一个NSLayoutConstraint 的实例来创建通过这个方法:

+ (id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1

relatedBy:(NSLayoutRelation)relation toItem:(id)view2

attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier

constant:(CGFloat)c

This method creates a single constraint using two layout attributes of two view objects.

这个方法用两个view的两个layout attributes来创建一个constraint .

The multiplier is the key to creating a constraint based on a ratio.

multiplier是基于比例创建一个constriant 的关键。

The constant is a fixed number of points, like you have used in your spacing constraints.

这个常量是一个固定的point就像你用来spacing constraints一样。

The layout attributes are defined as constants in the NSLayoutConstraint class:

这个layout  attributes 定义为NSLayoutConstraint类的一个常量。

   NSLayoutAttributeLeft

   NSLayoutAttributeRight

    NSLayoutAttributeTop

    NSLayoutAttributeBottom

    NSLayoutAttributeWidth

    NSLayoutAttributeHeight

    NSLayoutAttributeBaseline

    NSLayoutAttributeCenterX

    NSLayoutAttributeCenterY

    NSLayoutAttributeLeading

    NSLayoutAttributeTrailing

Let's consider a hypothetical constraint.Say you wanted the image view to be 1.5 times as wide as it is tall.

你想让你的image view 的宽度是高度的1.5 倍。

You cannot do this with a visual format string, so you would create it individually instead with the following code.

NSLayoutConstraint *aspectConstraint = [NSLayoutConstraint constraintWithItem:self.imageView

attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual

toItem:self.imageView attribute:NSLayoutAttributeHeight

multiplier:1.5 constant:0.0];

 
 

To understand how this method works, think of this constraint as the equation shown in

为了理解这个,我们可以把他们写成等式:

You relate a layout attribute of one view to the layout attribute of another view using a multiplier and a constant to define a single constraint.

 
 

To add a single constraint to a view, you use the method

- (void)addConstraint:(NSLayoutConstraint *)constraint

 
 

The same logic applies to decide which view should receive this message. When using this method, the determination is even easier to make because the affected view objects are the first and fourth arguments. In this case, the only affected object is the image view,

谁应该接受消息和上面的逻辑一样。 当你使用这个方法的时候,你能更容易的知道应该添加到哪个view上。因为第一和第四个参数已经指明了。

[self.imageView addConstraint:aspectConstraint];

 
 

7 NSAutoresizingMaskLayoutConstraint

Before Auto Layout, iOS applications used another system for managing layout: autoresizing masks.

在auto layout 之前,iOS应用使用另一套系统来管理layout:autoresizing masks。

Each view had an autoresizing mask that constrained the relationship between a view and its superview, but this mask could not affect relationships between sibling views.

每个view都有一个 autoresizing mask来限制一个view和它的superview 之间的关系,但是这个mask 不能影响两个sibling view 的关系。

By default, views create and add constraints based on their autoresizing mask. However, these translated constraints often conflict with your explicit constraints in your layout, which results an unsatisfiable constraints problem.

默认情况下,view 会create 和add 限制到他们的autoresizing mask。然而这些translated constraints经常与现在的layout冲突。

Let's look at the format of one of these constraints more closely.

让我们看看这些constraints限制的一个的格式:

<NSLayoutConstraint:0x9153fa0 UILabel:0x9149970.leading == UILabel:0x9149f00.leading>

This description indicates that the constraint located at memory address 0x9153fa0 is setting the leading edge of the UILabel (at 0x9149970) equal to the leading edge of the UILabel (at 0x9149f00).

 
 

The fifth, however, is an instance of NSAutoresizingMaskLayoutConstraint. This constraint is the product of the translation of the image view's autoresizing mask.

第五个NSAutoresizingMaskLayoutConstraint是这个image view 的autoresizing mask的一个产品。

Unfortunately, it chooses poorly and ignores one of your explicit instances of NSLayoutConstraint instead of the NSAutoresizingMaskLayoutConstraint.

The note before the constraints are listed is very helpful: the NSAutoresizingMaskLayoutConstraint needs to be removed.

// Do not produce a translated constraint for this view iv.translatesAutoresizingMaskIntoConstraints = NO;

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

    

iOS Programming Auto Layout: Programmatic Constraints 自动布局:通过编程限制的更多相关文章

  1. Auto Layout: Programmatic Constraints - BNR

    继续Auto Layout - BNR篇. 打开BNRDetailViewController.m文件,重载viewDidLoad方法来创建UIImageView对象.当你想要给通过加载NIB文件创建 ...

  2. Auto Layout Guide----(二)-----Auto Layout Without Constraints

    Auto Layout Without Constraints 没有约束的自动布局 Stack views provide an easy way to leverage the power of A ...

  3. [Android开发学iOS系列] Auto Layout

    [Android开发学iOS系列] Auto Layout 内容: 介绍什么是Auto Layout. 基本使用方法 在代码中写约束的方法 Auto Layout的原理 尺寸和优先级 Auto Lay ...

  4. iOS 7 - Auto Layout on iOS Versions prior to 6.0

    链接地址:http://stackoverflow.com/questions/18735847/ios-7-auto-layout-on-ios-versions-prior-to-6-0 Stac ...

  5. iOS 8 Auto Layout界面自动布局系列2-使用Xcode的Interface Builder添加布局约束

    http://blog.csdn.net/pucker/article/details/41843511 上一篇文章<iOS 8界面自动布局系列-1>简要介绍了iOS界面布局方式的前世今生 ...

  6. 【转 iOS 8 Auto Layout界面自动布局系列2-使用Xcode的Interface Builder添加布局约束

    原文网址:http://blog.csdn.net/pucker/article/details/41843511 上一篇文章<iOS 8界面自动布局系列-1>简要介绍了iOS界面布局方式 ...

  7. iOS 8 Auto Layout界面自动布局系列5-自身内容尺寸约束、修改约束、布局动画

    首先感谢众多网友的支持,最近我实在是事情太多,所以没有写太多.不过看到大家的反馈和评价,我还是要坚持挤出时间给大家分享我的经验.如果你对我写的东西有任何建议.意见或者疑问,请到我的CSDN博客留言: ...

  8. (iOS)使用auto layout进行复杂布局时,UILabel的相关trick

    本文转载至 http://blog.csdn.net/madongchunqiu/article/details/47960745  本文首发于CSDN:http://blog.csdn.net/ma ...

  9. IOS使用Auto Layout中的VFL适配

    做登录页面,之前做都是用frame做,今天想着用Auto Layout中的VFL来做.觉得做的效果还是可以的(自恋一下下). 首先看下效果图和标记图 自己在做的过程中也遇到了好多问题,不过也一个一个的 ...

随机推荐

  1. Android数据与服务器交互的GET,POST,HTTPGET,HTTPPOST的使用

    Android有这几种方式,可以提交数据到服务器,他们是怎么使用的呢,这里我们来探讨一下. 这里的例子用的都是提交客户端的用户名及密码,同时本节用到的StreamTools.readInputStre ...

  2. 强连通分量+poj2186

    强连通分量:两个点能够互相连通. 算法分解:第一步.正向dfs全部顶点,并后序遍历 第二步,将边反向,从最大边dfs,构成强连通分量 标号最大的节点属于DAG头部,cmp存一个强连通分量的拓扑序. p ...

  3. 对ASP.NET MVC 的路由一点理解

    这个东西,真搞不懂.看了网上的教程和文章,也不懂(也不清楚写那些文章的人自己是否真的懂).只好靠自己一顿乱摸索. 好比说,下面这个路由: //路由1 config.Routes.MapHttpRout ...

  4. 【转】Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)

    一.线程的状态 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线 ...

  5. 并不对劲的loj2134:uoj132:p2304:[NOI2015]小园丁与老司机

    题目大意 给出平面直角坐标系中\(n\)(\(n\leq5*10^4\))个点,第\(i\)个点的坐标是\(x_i,y_i(|x_i|\leq10^9,1\leq y_i\leq10^9)\),只有朝 ...

  6. BZOJ4561: [JLoi2016]圆的异或并 计算几何+treap

    因为本题保证两圆之间只有相包含或相离(不用担心两圆重合 因为我没有RE) 所以每个圆之间的相对位置是确定的  也就是可以按极角排序的, 所以可以按横坐标排序后 扫描同时用treap维护加圆删圆(即遇到 ...

  7. mod_python

    mod_python的确是一个让python程序员能够apache2写一些网站的工具.它是一个接口.过去一些python写的整站系统需要通过mod_python作为连接枢纽,将apache2与它们连接 ...

  8. memcached value最大限制只能是1M吗

    关于memcached的value最大是1M的限制很多人都知道,但是如果你以为我还要说这个事情,那你就错了. 之前的老版本确实是只能是1M,但是根据git记录,其实2009年以后的版本这个value最 ...

  9. openpyxl操作excel

    [转] openpyxl库可以读写xlsx格式的文件,对于xls旧格式的文件只能用xlrd读,xlwt写来完成了. python有很多模块都是用来操作excel的,比如xlrd,xlwt,pyExce ...

  10. robotframework执行用例时,报错selenium.common.exceptions.WebDriverException: Message: unknown error: cannot get automation extension from unknown error: page could not be found: chrome-extension://aapnijgdinl

    在用robotframework编写移动端测试用例(用chrome浏览器模拟手机浏览器),执行用例时, 报错selenium.common.exceptions.WebDriverException: ...