原文网址:http://www.cnblogs.com/HypeCheng/articles/4192154.html

DECEMBER 07, 2013

学习资料

文章

前两篇文章对如何在xcode 5中使用autolayout讲得已经很详细了。我使用了一段时间autolayout的感觉是,一般情况下都可以通过xcode的ib上直接设置autolayout的各种属性完成项目需求,除非遇到需求比较复杂的布局。

官方的Auto Layout Guide讲得详细易懂,推荐

WWDC视频

2012

2013

一些学习到的知识点整理

用代码创建一个 NSLayoutConstraint

下面的方法遵循一个计算公式:

view1.attribute1 = multiplier × view2.attribute2 + constant

1
2
3
4
5
6
7
+ (id)constraintWithItem:(id)view1
attribute:(NSLayoutAttribute)attribute1
relatedBy:(NSLayoutRelation)relation
toItem:(id)view2
attribute:(NSLayoutAttribute)attribute2
multiplier:(CGFloat)multiplier
constant:(CGFloat)constant;

例子:

  • Button.centerX = Superview.centerX
1
2
3
4
5
6
7
[NSLayoutConstraint constraintWithItem:button
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:NSLayoutAttributeCenterX
multiplier:1.0f
constant:0]
  • Button.bottom = Superview.bottom -
1
2
3
4
5
6
7
[NSLayoutConstraint constraintWithItem:button
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:NSLayoutAttributeBottom
multiplier:1.0f
constant:-padding]

创建完 NSLayoutConstraint 接下来要将它添加到 view 里,添加方法很简单,用 view 的- (void)addConstraint:(NSLayoutConstraint *)constraint添加。但是应该添加到哪个 view 里呢?

  1. 兄弟 view 的 Constraint 添加到他们的 superview

  2. 两个 view 的父 view 是兄弟关系的,Constraint 添加到父 view 的 superview 上

  3. 如果两个 view 是 parent-child 关系,Constraint 添加到 parent view上

跨层级 view 之间的 Constraint

有如下的视图层级:

- View
- UIScrollView
- UISwitch
- UIButton

其中UISwitch相对 UIScrollView 水平居中,和 ScrollView 同一层级有一个 UIButton,现在要始终保持 UIButton 的水平中点位置和 UISwitch 的水平中点位置在同一条线上。

为 UISwitch 的水平居中 Constraint 建立一个 IBOutlet。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 - (void)viewDidLoad {
[super viewDidLoad];
// Remove the IB-generated constraint centering the switch in its super view
[self.scrollView removeConstraint:self.horizontalSwitchConstraint] // Add a new constraint centering the switch on the button
NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:self.switchButton
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.button
attribute:NSLayoutAttributeCenterX
multiplier:1.0f
constant:0];
[self.view addConstraint:cn];
}

上面的的代码就实现了跨层级视图之间的 Constraint 设置。其实就是这么简单

设置Autolayout有两个原则

  • Ambiguous Layout(The constraints must be suficient)
  • Unsatisfiable Constraints(The constraints must not conflict)

在 IB 中设置明确的宽度

设置宽度有几个原则:

  • 如果一个 View 的宽高在显示的时候是不确定的:让 view 根据内容改变大小(size to fit size)
  • 如果一个 View 有确定的大小:改变其宽度的 Constraint Relation 为 >=
  • 正确的设置Content Hugging Priority(内容压缩优先级) 与 Content Compression Resistance Priority(内容抗压缩优先级)

Relation(Greater/Less) 与 Priority

Greater/Less 一般与 Priority 一起使用,为一个 Constraint 设置了 Greater/Less 后,调整 Priority。如果 Constraint 的 Priority 的值越大,程序优先设置它的 Constraint 效果。

如果两个 View 不在同一个层级,此时想要设置他们之间的 Constraint,只能通过代码实现。简单的方式是:先在 Xcode 中设置了 Constraint,然后为这个 Constraint 建立一个 IBOutlet,回到代码中,移除想要替换的 Constraint。

Content Hugging Priority 与 Content Compression Resistance Priority

含义:

  • Content Hugging Priority(内容压缩优先级)
  • Content Compression Resistance Priority(内容抗压缩优先级)。

如果 Constraint 发生冲突时,会先找优先级高的UIView,满足优先级高的UIView 的Constraint 后再依次找优先级低的 Constraint 满足,最后改变 View 的 Frame。如果发生多个 Constraint不能同时满足的情况,就发生了Unsatisfiable Constraints的错误。

Visual Format Language

VFL(Visual Format Language),提供了一种让代码以一种可视化的方式来设置不同 views 之间的 Constraint。

1
2
3
4
5
 [NSLayoutConstraint constraintsWithVisualFormat:@"[cancelButton]-[acceptButton]"] options:0 metrics:nil views:viewsDictionary];

  UIButton *cancelButton = ...
UIButton *acceptButton = ...
viewsDictionary = NSDictionaryOfVariableBindings(cancelButton, acceptButton);

Examples:

Property  Examples
Inequality,Priority  [wideView(>=60@700)]
Vertical:Flush Views,Equal Heights  V:[redBox][yellowBox(==redBox)]
Combination  H:|-[Find]-[FindNext]-[FindField(>=20)]-

 

Constraint 在什么时候更新

UIView中

-setNeesdDisplay
-setNeedsLayout
-setNeedsUpdateConstraints

UIView/UIWindow中

-layoutIfNeeded

关于 intrinsicContentSize

在 UIView 中有个方法-intrinsicContentSize,用于指定一个 view 的 width 和 height,设置了-intrinsicContentSize相当于设置一个不可变的长度或者宽度。有点像 UISlider 只能设置宽度,不能设置高度那样。

Debug

  1. 在 Xcode 中,设置 Autolayout 时可能出现3种状态,分别会出现黄色、红色、蓝色的线或线框。

    • 出现黄色的线或者线框表示:View 根据设置的 Constraints 最后计算出的 frame 位置和在xib 中 view 目前显示的位置不一致。此时并没有错误,只要更新一下 Update frames 以下就好
    • 出现红色的线或者线框表示:出现了Ambiguous Layout(Constraints 太少以至不能确定一个 view 的位置)或者Unsatisfiable Constraints(Constraints 有冲突,确定 view 一个方向上的 Constraints 超过1个)。这种情况要找到没有正确设置 Constraints 的 View 添加缺失的 Constraints 或者删除多余的 Constraints。
    • 蓝色线条或者线框表示这个 view 的 Constraints 正确设置,并且 view 目前显示的位置和 Constraints 计算得出的最终位置是在同一个地方。
  2. 在代码添加 Constraints 的 Debug 方法。

    • 在控制台输出AutolayoutTrace:po [[UIWindow keyWindow] _autolayoutTrace]。如果此时有Ambiguous LayoutUnsatisfiable Constraints,可以在输出的代码中看到。
  3. 有用的 debugging defaults

    • 双倍的国际化字符串:NSDoubleLocalizedStrings YES
    • 显示视图的对齐框: UIViewShowAlignmentRects YES

AutoresizingMask自动转化成 Constraint

view有一个 translatesAutoresizingMaskIntoConstraints 属性,如果设置为 NO,那么在运行时,程序不会自动将AutoresizingMask转化成 Constraint。

Animation

关键是在 UIView Animation 中调用[view layoutIfNeeded]

1
2
3
4
5
6

[UIview animateWithDuration:1.0 animations:^{
// Constraint Changed... [view layoutIfNeeded];
}];

Github上一些好用的Autolayout第三方库

IOSIOS学习之AUTOLAYOUT WAS PUBLISHED ON DECEMBER 07, 2013 VITO ZHANG

iOS UITextView 输入内容实时更新 cell 的高度

这篇文章介绍了在一个动态数据的 table view 中,cell 根据 text view 内容的输入实时改变 cell 和 table view 的高度。自动计算 cell 高度的功能使用 iOS 8 才支持的自适应 cell,如果你还不知道 iOS 8 自适应 cell, …… Continue reading

iOS 8 自适应 Cell

Published on November 13, 2014

© 2014 Vito Zhang. Powered by Octopress using the HPSTR Theme for Octopress.

【转】iOS学习之Autolayout(代码添加约束) -- 不错不错的更多相关文章

  1. iOS学习笔记——AutoLayout的约束

    iOS学习笔记——AutoLayout约束 之前在开发iOS app时一直以为苹果的布局是绝对布局,在IB中拖拉控件运行或者直接使用代码去调整控件都会发上一些不尽人意的结果,后来发现iOS在引入了Au ...

  2. IOS AutoLayout 代码实现约束—VFL

    在autolayout下,尽管使用IB来拖放控件,但仍然避免不了用代码来创建控件,这是约束需要代码来实现. IOS 提供了两种添加约束的方法 第一种: +(instancetype)constrain ...

  3. IOS NSLayoutConstraint 页面布局(通过代码添加约束)

    #import "ViewController.h" @interface ViewController () @property (nonatomic, strong) UIVi ...

  4. 【转】iOS6中的Auto Layout:通过代码添加约束

        最近做的项目用到了Auto Layout,于是经过了一番大量的google,这是我看到的讲用代码创建约束最清晰的一篇教程,于是想跟更多的人分享一下.原文也比较简单,可以直接过去看,如果我翻译的 ...

  5. iOS学习之Autolayout

    转载自:http://vit0.com/blog/2013/12/07/iosxue-xi-zhi-autolayout/ 学习资料 文章 Beginning Auto Layout Tutorial ...

  6. ios UIScrolloView在storyboard中添加约束

    1.在storyboard中如果有UINavigationbar 或 UITabar 布局的时候需要在控制器中勾选掉 Under Top Bars 和 Under Bottom Bars 这两个选项. ...

  7. IOS学习4——block代码块

    本文转载自:iOS开发-由浅至深学习block 一.关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调.这不免让我们想 ...

  8. IOS学习之block代码块

    前言: block这个名词对于做一般开发者来说可能会觉得稀奇古怪而非常陌生,但是对于iOS工程师来说,在整个开发中到处都是它的影子,今天一大早觉得在假期学习一下它,对明年的iOS开发工作做个准备,突然 ...

  9. iOS: 学习笔记, 用代码驱动自动布局实例(swift)

    iOS自动布局是设置iOS界面的利器.本实例展示了如何使用自动布局语言设置水平布局, 垂直布局1. 创建空白iOS项目(swift)2. 添加一个控制器类, 修改YYAppDelegate.swift ...

随机推荐

  1. memmove和memcpy 以及strcmp strcpy几个库函数的实现

    memmove和memcpy 1.memmove 函数原型:void *memmove(void *dest, const void *source, size_t count) 返回值说明:返回指向 ...

  2. 【WCF--初入江湖】10 序列化和传输大型数据流

    10 序列化和传输大型数据流 1.前言 理解WCF的序列化形式 掌握DataContractSerializer序列化对象 比较性能 比较xmlSerializer序列化对象   大数据量传输设置 修 ...

  3. linux服务器重启服务命令说明文档

    (前提是电脑上面已经安装好了ssh软件~!)输入ip,用户名,端口(默认22) 输入密码,登陆成功之后, 转入到/usr/local/tomcat/bin 目录,输入命令行: [root@yangch ...

  4. css table表格无法调整宽度问题分析

    1.在网上查找了相关问题,有的说表格设置了背景图片,把原来的宽度撑开了,导致无法变窄~! 在项目中,原来美工设计的页面,设置了一个块的样式class="title",现在有一段ht ...

  5. servlet中获取request中文乱码问题分析

    request.setCharacterEncoding("utf-8");//第一种情况 log.info("服务商名称:" + request.getPar ...

  6. Create a method synchronized without using synchronized keyword

    Actually, lots of ways: No need for synchronization at all if you don't have mutable state. No need ...

  7. Kibana

    https://github.com/moonstack/moon-kibana.git

  8. 欧拉工程第67题:Maximum path sum II

    By starting at the top of the triangle below and moving to adjacent numbers on the row below, the ma ...

  9. 【Linux高频命令专题(10)】mv

    概述 mv命令是move的缩写,可以用来移动文件或者将文件改名(move (rename) files),是Linux系统下常用的命令,经常用来备份文件或者目录. 命令格式 mv [选项] 源文件或目 ...

  10. java socket知识点

    3.用线程池实现TCP服务器端时,首先创建一个ServerSocket实例,然后创建N个线程,每个线程反复循环,从(共享的)ServerSocket实例接收客户端连接.当多个线程同时调用一个Serve ...