AutoLayout 代码使用方法

---2016年01月20日12:52:18 更新-----
使用 VFL 的朋友可以参考下简单的封装
https://github.com/zhangqingyv/QYAutolayout


基本概念

概要

为什么要用Auto Layout?

  • 解决不同尺寸屏幕的适配问题
  • 解决屏幕的旋转的适配问题

什么是Auto Layout?

在自动布局中基本构建块是约束(constraint)。约束表现在你的界面元素的布局规则,例如,您可以创建一个约束,指定该元素的宽度,或跟另一个元素的水平距离。你可以通过添加和删除约束,或改变约束的性质,来影响你的界面布局。。

当正在计算用户界面元素的运行位置时,自动布局系统同时考虑所有约束,以最能满足所有的约束来设置位置。

以下几点是我们在开始使用之前必须弄清楚的事情:

  1. 我们要抛弃以往旧的布局方式不再去关注View的Frame,Center,和autoresizing. 因为这些坐标和大小的定位都可以通过来Auto Layout完成.
  2. 理解每一种Constraint的含义,否则,当你去看别人的实现的Constraint时,就会有种看天书的感觉.
  3. 按意图设计,一切按我们理想中的效果去布局,只要约束设定的合理,就一定能够完成目标布局.

什么是约束 [NSLayoutConstraint]

你可以把约束想象为一个:表达语句的数学表达方式。例如,如果你定义一个按钮的位置,你可能会说“左边缘应该是:距离它的父视图的左边缘20points。”

  • 构造函数:constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
  • 表达式:"view1.attr1 <relation> view2.attr2 * multiplier + constant"

其他的属性设置:

  • 优先级(Priority level)约束还有优先级。先满足较高优先级的约束而后满足较低优先级的约束。默认的优先级(NSLayoutPriorityRequired)意味着,约束必须精确地满足。即使它不能完全实现,布局系统应该尽可能接近来满足可选的约束。
    优先级允许你表达有用的条件行为。例如,它们被用来表达某些控件应该始终是,大小适配他们的内容,除非有优先级更高更重要的东西。对于优先级的更多信息,请参阅NSLayoutPriority。

约束是累加的,不互相覆盖。如果你有一个现有的约束,再设置另一个相同类型的约束,它不会覆盖前一个。例如,为视图设置第二宽度约束不删除或改变第一宽度约束。---事实上你需要手动删除第一个约束。

控制器的作用

虽然视图指定其内​​在的内容的大小,视图的用户指定其重要性。例如,默认情况下,一个按钮:

  • 强烈地想要在垂直方向拥抱它的内容(按钮真的应该是他们的自然高度)
  • 水平方向拥抱其内容(额外的侧面填充标题和边缘之间的挡板是可以接受的)
  • 在两个方向强烈抵抗压缩或剪切的内容

使用方法

使用 Autolayout 的一般流程

  1. 添加约束之前必须讲view添加到superview里
  2. 对于要使用Auto Layout的控件需要关闭Autoresizing
  3. 创建并添加约束
  4. 更新约束

创建约束【Constraint】的方法

VFL(Visual Format Language) 方式

构造函数

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

代码示范

//dict和metrics相当于vfl中的名称与对象和数值的映射
    NSDictionary *dict = NSDictionaryOfVariableBindings(viewTopLeft, viewTopRight, viewBottom);
    //相当于这么写 NSDictionary *dict = @[@"viewTopLeft":viewTopLeft, @"viewTopRight":viewTopRight, @"viewBottom",viewBottom];不一定名称要与对象名一致
    NSDictionary *metrics = @{@"pad":@10};
    
    //水平关系(H:,可省略如vfl1),"|"相当与superview,"-"是连接符,表示两者间的间距也可以没有表示无间距
    //转化正自然语言的描述就是:superview的左边界间隔pad距离是viewTopLeft(宽度与viewTopRight相等)再间隔默认距离是viewTopRight再间隔10的距离是superview的右边界。
    NSString *vfl0 = @"H:|-pad-[viewTopLeft(==viewTopRight)]-[viewTopRight]-10-|";
    NSString *vfl1 = @"|[viewBottom]|";
    
    //垂直关系(V:)
    NSString *vfl2 = @"V:|-[viewTopLeft(==viewBottom)]-[viewBottom]-pad-|";
    NSString *vfl3 = @"V:|-[viewTopRight]-[viewBottom]-pad-|";
    
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl0 options:0 metrics:metrics views:dict]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl1 options:0 metrics:metrics views:dict]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl2 options:0 metrics:metrics views:dict]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl3 options:0 metrics:metrics views:dict]];

** VFL 语法**

普通代码方式

构造函数

+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c

代码示范

     //viewTopLeft的leading与其superview的leading(左侧)对齐
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:viewTopLeft attribute:NSLayoutAttributeLeading multiplier:1 constant:-10]];
    
    //viewTopLeft的top与其superview的top对齐
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:viewTopLeft attribute:NSLayoutAttributeTop multiplier:1 constant:-10]];
    
    //viewTopRight的top与viewTopLeft的top对齐
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewTopRight attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:viewTopLeft attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
    
    //viewTopRight的leading与viewTopLeft的trailing(右侧)对齐
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewTopRight attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:viewTopLeft attribute:NSLayoutAttributeTrailing multiplier:1 constant:10]];
    
    //viewTopRight的trailing与其superview的右侧对其
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewTopRight attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:-10]];
    
    //viewTopRight的宽与viewTopLeft宽相等
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewTopRight attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:viewTopLeft attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];
    
    //viewTopRight的高与viewTopLeft高相等
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewTopLeft attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:viewTopRight attribute:NSLayoutAttributeHeight multiplier:1 constant:0]];
    
    //viewBottom的top与viewTopRight的bottom对齐
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewBottom attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:viewTopRight attribute:NSLayoutAttributeBottom multiplier:1 constant:10]];
    
    //viewBottom的bottom与superview的bottom对齐
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewBottom attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:-10]];
    
    //viewBottom的leading与viewTopLeft的leading对齐
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewBottom attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:viewTopLeft attribute:NSLayoutAttributeLeading multiplier:1 constant:0]];
    
    //viewBottom的高与viewTopLeft的高相等
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewBottom attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:viewTopLeft attribute:NSLayoutAttributeHeight multiplier:1 constant:0]];
    
    //viewBottom的宽与其superview的高相等
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:viewBottom attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1 constant:-20]];

注意点

  1. 约束必须有给定的size然后通过约束计算出各个view的size和位置,上面self.view的size是给定的,如果superview的size不固定则 必须 给定某个subview的size才能通过约束计算出其他的。
  2. 两个view之间的约束应该放在他们superview上,如果一个view是superview只要放在superview的那个上就行了。
  3. 约束的设计最好不要冲突,虽然可以设置优先级,但是容易出问题。
  4. VFL方式的设置view的size时只有相等,小等或大等3种关系,没法像使用方法生成约束那样可以设置两个view的比例,所以在具体的应用中还是要两者结合起来使用。

UIView+AutoLayout
Build Status
Build Status

The ultimate API for iOS Auto Layout -- impressively simple, immensely powerful. Comprised of categories on UIView, NSArray, and NSLayoutConstraint.

UIView+AutoLayout provides a developer-friendly interface for the vast majority of Auto Layout use cases. It is designed for clarity and simplicity, taking inspiration from the Auto Layout UI options available in Interface Builder but delivering far more flexibility and capability. The API is also highly efficient, as it adds only a thin layer of third party code and is engineered for maximum performance (for example, by automatically adding constraints to the nearest ancestor view).

API Cheat Sheet

This is just a handy overview of the core API methods. Check out the header file for the full API and documentation. A couple notes:

  • All of the API methods begin with auto... for easy autocompletion!
  • All methods that generate constraints also automatically add the constraint(s) to the correct view, then return the newly created constraint(s) for you to optionally store for later adjustment or removal.
  • Many methods below also have a variant which includes a relation: parameter to make the constraint an inequality.

UIView

+ autoRemoveConstraint(s):
- autoRemoveConstraintsAffectingView(AndSubviews)
+ autoSetPriority:forConstraints:
- autoSetContent(CompressionResistance|Hugging)PriorityForAxis:
- autoCenterInSuperview:
- autoAlignAxisToSuperviewAxis:
- autoPinEdgeToSuperviewEdge:withInset:
- autoPinEdgesToSuperviewEdges:withInsets:(excludingEdge:)
- autoPinEdge:toEdge:ofView:(withOffset:)
- autoAlignAxis:toSameAxisOfView:(withOffset:)
- autoMatchDimension:toDimension:ofView:(withOffset:|withMultiplier:)
- autoSetDimension(s)ToSize:
- autoConstrainAttribute:toAttribute:ofView:(withOffset:|withMultiplier:)
- autoPinTo(Top|Bottom)LayoutGuideOfViewController:withInset:

NSArray

- autoAlignViewsToEdge:
- autoAlignViewsToAxis:
- autoMatchViewsDimension:
- autoSetViewsDimension:toSize:
- autoDistributeViewsAlongAxis:withFixedSpacing:(insetSpacing:)alignment:
- autoDistributeViewsAlongAxis:withFixedSize:(insetSpacing:)alignment:

NSLayoutConstraint

- autoInstall
- autoRemove

UIView+AutoLayout vs. the rest

An overview of the Auto Layout options available, ordered from the lowest- to highest-level of abstraction.

  • Apple NSLayoutConstraint SDK API
    • Pros: Raw power
    • Cons: Extremely verbose, tedious to write, difficult to read
  • Apple Visual Format Language
    • Pros: Concise, convenient
    • Cons: Doesn't support some use cases, incomplete compile-time checks, must learn syntax, hard to debug
  • Apple Interface Builder
    • Pros: Visual, simple
    • Cons: Difficult for complex layouts, cannot dynamically set constraints at runtime, encourages hardcoded magic numbers, not always WYSIWYG
  • UIView+AutoLayout
    • Pros: Simple, efficient, built directly on the iOS SDK, minimal third party code
    • Cons: Not the most concise or pure expression of layout code
  • High-level layout frameworks (Masonry, KeepLayout)
    • Pros: Very clean, simple, and convenient
    • Cons: Heavy dependency on third party code, cannot mix with SDK APIs, potential compatibility issues with SDK changes, overloaded Objective-C syntax

个人使用过程中遇到的坑

  • UINavigationBar 添加AutoLayout 的 subview 可能会有 crashed 问题
    • 解决办法 暂无
  • TabelViewCell 使用 Autolayout ,添加到 self.contentView
  • 网上说使用 TabelViewCell 向 self.view 添加 subview 可能会有 crashed 问题
    • self.contentView
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容