iOS AutoLayout
iOS AutoLayout
Autolayout
是一种全新的布局技术,专门用来布局UI界面的,用来取代Frame布局在遇见屏幕尺寸多重多样的问题。Autolayout自iOS 6开始引入,但是由于Xcode 4的不给力,当时并没有得到大规模推广。在iOS 7(Xcode5)开始,Autolayout的开发效率得到很大的提升,苹果官方也推荐开发者尽量使用Autolayout来布局UI界面,减少纯代码的方式。在iOS6之前是用Autoresize
布局.Autolayout
的好处是能够很方便的适配各种尺寸的屏幕,并且当很好的适配屏幕的横向和竖向,不会造成使用在有些手机上显示不全,或者横竖屏后布局错位的问题.Autolayout
父视图去添加对子视图的约束,Autoresize
是子视图添加都父视图的相对位置和大小.
AutoLayout的使用
- AutoLayout常见的使用方式有两种:
1.IB方式即StoryBoard
,Xib
;
2.纯代码方式即VFL
,NSLayoutConstraint
,Masonry
,SnapKit
.
1.IB方式实现自动布局
在xib或者stroyBoard中添加约束的核心思想是一定要确定视图的frame,不管是设置(Leading,Top,Width,Height),还是设置距离上下左右的间距都是为了确定视图的farme,根据需求做不同的设置.如果是设置上下左右的间距固定,则视图的尺寸会不同尺寸的手机显示的大小不同,如果设置的是Width,Height以及Leading(或者Trailing),Top(或者Bottom),则实体的长宽固定,而没有添加约束的两条边的边距根据手机的尺寸不同而不同.总至要至少要添加四条约束.
但是有些控件添加两条约束Leading(或者Trailing),Top(或者Bottom)也是可以的,如
UILabel
,UIimageView
,UIButton
,如果不设置宽高这些控件会根据内容自动调整大小.IB自动布局大家都比较熟悉,这里就不再详述.
2.VFL/NSLayoutConstrais方式实现自动布局
VFL(Virsual Format Language)
是一种虚拟的格式化语言,主要用来创建AutoLayout的约束字符串。- VFL官网介绍
- VFL基本语法介绍:例如:
"V:[view1]-0-[view2(==100@1000)]-<=0-|"
功能 | 表达式 |
---|---|
垂直方向 | V: |
水平方向 | H: |
Views | [view1],[View2] |
SuperView |
|
|
关系(不写默认==) | >=,==,<= |
空间,间隙(不写默认值8) | - |
优先级 | @value |
- 示例:添加上中下三个视图,上中视图等高,下视图距中间视图底部的间隙8,并且占满屏幕剩余部分.
let topView = UIView()topView.backgroundColor = UIColor.redtopView.translatesAutoresizingMaskIntoConstraints = falselet middleView = UIView()middleView.backgroundColor = UIColor.greenmiddleView.translatesAutoresizingMaskIntoConstraints = falselet bottomView = UIView()bottomView.backgroundColor = UIColor.bluebottomView.translatesAutoresizingMaskIntoConstraints = falseview.addSubview(topView)view.addSubview(middleView)view.addSubview(bottomView)/*oc 中 NSDictionaryOfVariableBindings(v1,v2,v3)相当于[NSDictionary dictionaryWithObjectsAndKeys:v1,@“v1”,v2,@“v2”,v3,@“v3”,nil]*///水平约束,当为==时==可以省略let topViewHorizontalContriants = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[topView]-==0-|", options:[], metrics: nil, views: ["topView":topView])view.addConstraints(topViewHorizontalContriants)//垂直约束let topViewVContriants = NSLayoutConstraint.constraints(withVisualFormat: "V:|-64-[topView(==100@1000)]", options: [], metrics: nil, views: ["topView":topView])view.addConstraints(topViewVContriants)//middleView的顶部和topView的底部对齐let middleTopC = NSLayoutConstraint.init(item: middleView, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: topView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1.0, constant: 0)//middleView的左边和topView的左边对齐对齐view.addConstraint(middleTopC)let middleleftC = NSLayoutConstraint.init(item: middleView, attribute: NSLayoutConstraint.Attribute.left, relatedBy: NSLayoutConstraint.Relation.equal, toItem: topView, attribute: NSLayoutConstraint.Attribute.left, multiplier: 1.0, constant: 0)view.addConstraint(middleleftC)//middleView的宽等于topView的宽度let middleWidthC = NSLayoutConstraint.init(item: middleView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: topView, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1.0, constant: 0)view.addConstraint(middleWidthC)//middleView的高度等于topView的高度let middleHeigitC = NSLayoutConstraint.init(item: middleView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: topView, attribute: NSLayoutConstraint.Attribute.height, multiplier: 1.0, constant: 0)view.addConstraint(middleHeigitC)//bottomView的垂直方向上的约束,不写间距默认是8let bottomVC = NSLayoutConstraint.constraints(withVisualFormat: "V:[middleView]-[bottomView]-0-|", options: [], metrics: nil, views: ["middleView":middleView,"bottomView":bottomView])view .addConstraints(bottomVC)//水平约束let bottomHC = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[bottomView]-0-|", options: [], metrics: nil, views: ["bottomView":bottomView])view.addConstraints(bottomHC)
- 给下面蓝色视图添加一个UILabel,使其上左右边距为10,高度自适应
let label = UILabel()label.translatesAutoresizingMaskIntoConstraints = falselabel.font = UIFont.systemFont(ofSize: 15)label.numberOfLines = 0;label.backgroundColor = UIColor.cyanbottomView.addSubview(label)//水平约束let labelHC = NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[label]-10-|", options: [], metrics: nil, views: ["label":label])bottomView.addConstraints(labelHC)//垂直约束,顶部对齐,高度自适应let labelVC = NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[label]", options: [], metrics: nil, views: ["label":label])bottomView.addConstraints(labelVC)label.text = "lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世vlalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三lalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世vlalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三lalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世vlalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三lalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世vlalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三lalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世vlalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三lalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世lalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世vlalalalalaz汽车消费网lalalalalaz汽车消费网lalalalalaz三生三世"print(bottomView.constraints)
// label.frame.size = CGSize(width: 10, height: 10)UIView.animate(withDuration: 3) {// self.label.setNeedsUpdateConstraints()self.label.layoutIfNeeded()}
- 删除约束,更新布局
extension ViewController {override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {let labelHC1 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-60-[label]-60-|", options: [], metrics: nil, views: ["label":label])bottomView.removeConstraints(labelHC!)bottomView.addConstraints(labelHC1)UIView.animate(withDuration: 3) {// self.bottomView.setNeedsUpdateConstraints()self.bottomView.layoutIfNeeded()
// self.bottomView.updateConstraints()
// self.bottomView.updateConstraintsIfNeeded()}}
}
小结
- 上面可以看出:
NSLayoutConstraint
的constraints
方法是通过VFL
添加水平和垂直方向约束来进行自动布局,而NSLayoutConstraint
的便利构造方法是通过添加上下左右间距或间距和大小来添加约束来自动布局,两者单独使用或结合使用都可以,各有优缺点,一般会结合使用.
/*
withVisualFormat : VFL语句
options : 字典类型的值;这里的值一般在系统定义的一个enum里面选取,默认传空的字典
metrics : 一般为nil ,参数类型为NSDictionary,从外部传入 //衡量标准
views : 就是上面所加入到NSDictionary中的绑定的View,要求字典形式为 ["view":view,"label":label]
*/
open class func constraints(withVisualFormat format: String, options opts: NSLayoutConstraint.FormatOptions = [], metrics: [String : Any]?, views: [String : Any]) -> [NSLayoutConstraint]
/*
item : 指定需要添加约束的视图
attr1 : 指定视图一需要约束的属性
relatedBy : 指定视图一和视图二添加约束的关系(lessThanOrEqual 小于等于,equal 等于,greaterThanOrEqual 大于等于)
toItem : 指定视图一依赖关系的视图二;可为nil
attr2 : 指定视图一所依赖的视图二的属性,若view2=nil,该属性设置 NSLayoutAttributeNotAnAttribute
multiplier : 系数,情况一:设置A视图的高度 = A视图高度 * multiplier + constant;此时才会起作用;情况二:设置A视图和其他视图的关系或 toItem=nil,multiplier设置不等于0即可,若等于0会crash;
constant :常量,间距的值
*/public convenience init(item view1: Any, attribute attr1: NSLayoutConstraint.Attribute, relatedBy relation: NSLayoutConstraint.Relation, toItem view2: Any?, attribute attr2: NSLayoutConstraint.Attribute, multiplier: CGFloat, constant c: CGFloat)
oc 中
NSDictionaryOfVariableBindings(v1,v2,v3)
宏相当于[NSDictionary dictionaryWithObjectsAndKeys:v1,@“v1”,v2,@“v2”,v3,@“v3”,nil]
父控件是谁,这些约束就添加给谁.
UIView
的open var translatesAutoresizingMaskIntoConstraints: Bool
属性,把 autoresizingMask 转换为 Constraints,即:可以把 frame ,bouds,center 方式布局的视图自动转化为约束形式。(此时该视图上约束已经足够 不需要手动去添加别的约束).用代码创建的所有view , translatesAutoresizingMaskIntoConstraints 默认是 true,用 IB 创建的所有 view ,translatesAutoresizingMaskIntoConstraints 默认是 false . 如果用代码约束布局,则需要将该属性设置为false.
translatesAutoresizingMaskIntoConstraints
属性
autoresize布局:
true,
autolayout布局 :
false`.在更新约束时,要先删除一些约束
removeConstraints
,再添加对应的一些约束addConstraints
,然后跟新约束才有有效.项目开发过程中,通常使用的是
Masonry\SnapKit
自动布局的三方库,简单高效。较之frame布局,自动布局更适合业务拓展。
基于约束的AutoLayer更新约束的方法
1、setNeedsUpdateConstraints
当一个自定义view的某个属性发生改变,并且可能影响到constraint时,需要调用此方法去标记constraints需要在未来的某个点更新,系统然后调用updateConstraints.
2、needsUpdateConstraints
constraint-based layout system
使用此返回值去决定是否需要调用updateConstraints
作为正常布局过程的一部分。
3、updateConstraintsIfNeeded
立即触发约束更新,自动更新布局。
4、updateConstraints
自定义view应该重写此方法在其中建立constraints
. 注意:要在实现在最后调用[super updateConstraints]
uto Layout Process
自动布局过程
与使用springs and struts(autoresizingMask)
比较,Auto layout在view显示之前,多引入了两个步骤:updating constraints 和laying out views。每一个步骤都依赖于上一个。display依赖layout,而layout依赖updating constraints。 updating constraints->layout->display
第一步:updating constraints,被称为测量阶段,其从下向上(from subview to super view),为下一步layout准备信息。可以通过调用方法setNeedUpdateConstraints去触发此步。constraints的改变也会自动的触发此步。但是,当你自定义view的时候,如果一些改变可能会影响到布局的时候,通常需要自己去通知Auto layout,updateConstraintsIfNeeded。
自定义view的话,通常可以重写updateConstraints方法,在其中可以添加view需要的局部的contraints。
第二步:layout,其从上向下(from super view to subview),此步主要应用上一步的信息去设置view的center和bounds。可以通过调用setNeedsLayout去触发此步骤,此方法不会立即应用layout。如果想要系统立即的更新layout,可以调用layoutIfNeeded。另外,自定义view可以重写方法layoutSubViews来在layout的工程中得到更多的定制化效果。
第三步:display,此步时把view渲染到屏幕上,它与你是否使用Auto layout无关,其操作是从上向下(from super view to subview),通过调用setNeedsDisplay触发,
因为每一步都依赖前一步,因此一个display可能会触发layout,当有任何layout没有被处理的时候,同理,layout可能会触发updating constraints,当constraint system更新改变的时候。
需要注意的是,这三步不是单向的,constraint-based layout是一个迭代的过程,layout过程中,可能去改变constraints,有一次触发updating constraints,进行一轮layout过程。
注意:如果你每一次调用自定义layoutSubviews都会导致另一个布局传递,那么你将会陷入一个无限循环中。
相关参考
VFL的简单使用教程
iOS-手动添加限制-constraintsWithVisualForm
translatesAutoresizingMaskIntoConstraints 详解
自动布局之-NSLayoutConstraint
Autoresize和Autolayout 布局的实现
iOS AutoLayout全解
setNeedsUpdateConstraints,needsUpdateConstraints等基于约束的AutoLayer的方法
ios – setNeedsLayout vs. setNeedsUpdateConstraints and layoutIfNeeded vs updateConstraintsIfNeeded
MY_updateConstraintsIfNeeded,setNeedsLayout, layoutIfNeeded 和 layoutSubviews 方法之间的关系解释
iOS自动约束】四个重要的系统方法
UIStackView
Stack
相关源码(包括
AutoLayout,Masonry,SnapKit
):AutoLayoutStudy
iOS AutoLayout相关推荐
- iOS AutoLayout使用技巧
关于ContentCompressionResistance, ContentHugging运用 如下图效果图,两个Label并列在同一排上,左边label自适应,右边label(红色)要使得内容全部 ...
- iOS - AutoLayout
前言 NS_CLASS_AVAILABLE_IOS(6_0) @interface NSLayoutConstraint : NSObject@available(iOS 6.0, *) public ...
- iOS Autolayout笔记
一.Autolayout笔记 上午: 第一节 1.PPT介绍页面布局的三个时期 2.Autosizing简单使用1如何固定控件和四周的距离>讲解如何开启Autosizing (去掉Use Aut ...
- iOS autolayout
http://blog.csdn.net/dizzthxl/article/details/9009537 (基本用法) http://blog.csdn.net/ysy44 ...
- iOS autolayout 约束冲突添加symbol breakpoint
UIViewAlertForUnsatisfiableConstraints
- ios charts显示固定个数_上次挂在了百度iOS二面不服气, 三月之期已到,这次终于拿下offer!...
笔试.面试题 1.算法题 (1).请在1000万个整型数据中以最快的速度找出其中最大的1000个数? 这是一个经常被问到的问题,百度网上解法也很多. 这里仅提供基本思路,供参考:把1000万的整型平均 ...
- Android和IOS的区别和联系
关于开发语言的历史可以参看:计算机和编程语言的发展历史 关于Android和IOS的发展历史可以参看:Android和IOS的发展历史 开发语言不同 1.IOS使用的是ObjectC和Swift 2. ...
- iOS 强大第三方资源库
Github用法 git-recipesGit recipes in Chinese. 高质量的Git中文教程. lark怎样在Github上面贡献代码 my-git有关 git 的学习资料 giti ...
- 技术周刊 Vol.7 - 【iOS丨好好学习,从娃抓起~】
优质阅读感受及更多讨论,请查看原文: https://segmentfault.com/a/1190000007021303 我有一程序员朋友阿温,92 年,高个子,体型偏瘦,平时不善言辞,比较低调. ...
- SegmentFault 技术周刊 Vol.7 - iOS丨好好学习,从娃抓起~
我有一程序员朋友阿温,92 年,高个子,体型偏瘦,平时不善言辞,比较低调.最近,阿温家小娃出生,让他当了一回公司的热议人物. 事情是这样的,那会儿大家都还在睡午觉,只听阿温一声猝不及防的喊声,接下来便 ...
最新文章
- GDCM:智能指针的测试程序
- matlab验证对称三相电路,不对称三相电路中,中线的电流为()。 A.0 B. C. D....
- java阿里云短信服务开通验证码功能实现(1)
- java项目引入json配置,TS-28 配置tsconfig.json(3):工程引用
- 遍历Page的Controls集合
- 新版php卡盟排行榜网站源码
- python车流量检测车流统计车辆计数yolov5 deepsort车流检测
- python二叉树的非递归遍历
- 如何解决Mac电脑键盘上的大写锁定键灯不亮?
- Acwing 1402.星空之夜
- MFC界面编程基础(01):Windows 编程模型
- 桌面图标白色大块异常恢复
- matlab中lab颜色空间,使用Matlab绘制图像的rgb颜色空间和Lab颜色空间分量图和分量直方图...
- java 系统资源不足_[InteliJ IDEA] 系统资源不足
- 大学计算机课代表竞选稿,音乐课代表竞选稿
- Learning Texture Transformer Network for Image Super-Resolution(全译文+大量名词链接)读论文记录①
- 扑克牌游戏——老牛拉破车
- 微信小程序开发(一) 微信登录流程
- 在线JSONPath解析器
- url和超级url的区别
热门文章
- 在xp中运行 .air 文件--Adobe AIR Runtime for Window
- cadz轴归零命令_CAD的Z轴归零的插件分享
- Windows 2008 R2 远程桌面服务(四)运行RemoteApp程序
- PreferenceActivity的使用
- 【题目记录】——2021 年百度之星·程序设计大赛 - 初赛二
- 如何复制百度文库上的东西
- php动态网站程序设计课后答案,《PHP动态网站开发实例教程》课程标准
- 泛微oa服务器文件,泛微oa云服务器要求
- 联网JAVA模拟器_java模拟器
- 通信系统中各网络设备时间同步要求