iOS自动布局

自动布局


技术博客http://www.cnblogs.com/ChenYilong/ 
新浪微博http://weibo.com/luohanchenyilong 




自动布局 
技术博客http://www.cnblogs.com/ChenYilong/新浪微博http://weibo.com/luohanchenyilong
 
问题 
• iOS程序中,大部分视图控制器都包含了大量的代码用 于设置UI布局,设置控件的水平或垂直位置,以确保组件 在不同版本的iOS中都能得到合理的布局
• 甚至有些程序员希望在不同的设备使用相同的视图控制器, 这就给代码添加了更多的复杂性!
 自动布局AutoLayout的引入很好地解决了这一问题! 



测试演练1--使用AutoSizing 
• Main.sotryboard的正中间中添加一个按钮,并使用AutoSizing尝试调
整按钮位置 
• 经过运行测试不难发现,不仅在不同分辨率的设备上运行效果不同, 而且在不同的版本上运行的表现也不一致 

定义 
• AutoLayout是一种基于约束的,描述性的布局系统
- 基于约束:和以往定义frame的位置和尺寸不同,AutoLayout的位 置确定是以所谓相对位置的约束来定义的,比如x坐标为superView 的中心,y坐标为屏幕底部上方10像素等 
- 描述性:约束的定义和各个view的关系使用接近自然语言或者可视 化语言的方法来进行描述 
- 布局系统:用来负责界面的各个元素的位置 
• AutoLayout为开发者提供了一种不同于传统对于UI元素位置指定的布 局方法。以前,不论是在IB里拖放,还是在代码中写,每个UIView都 会有自己的frame属性,来定义其在当前视图中的位置和尺寸。而使 用AutoLayout,就变为了使用约束条件来定义view的位置和尺寸 

AutoLayout的优势 
 解决不同分辨率和屏幕尺寸下view的适配问题,同时也简化了旋转时 view的位置的定义。原来在底部之上10像素居中的view,不论在旋转 屏幕或是更换设备(iPadiPad miniiPhone 4或者是iPhone5)的时 候,始终还在底部之上10像素居中的位置,不会发生变化
 使用约束条件来描述布局,viewframe会依据这些约束来进行计算

测试演练2--Storyboard中使用自动布局 
• Storyboard中为一个屏幕居中的按钮添加水平居中和垂直居中的布
局约束
• 经过运行测试不难发现,添加了自动布局之后,在不同分辨率的设备 以及不同的版本的设备上运行时该按钮始终会保持在屏幕中间

测试演练3--Storyboard中使用自动布局 
• 以前一演练为基础,分别在垂直方向上,上下各放置间距20点的两个
按钮
• 经过运行测试不难发现,在不同分辨率的设备以及不同的版本的设备 上运行时该按钮始终会保持在屏幕中间,而且无需编写任何的代码!

AutoLayoutAutoresizing Mask的区别 
 iOS6之前,关于屏幕旋转的适配和iPhone,iPad屏幕的自动适 配,基本都是由Autoresizing Mask来完成的。但是随着大家对 iOS App的要求越来越高,以及今后可能出现的多种屏幕和分辨 率的设备,Autoresizing Mask显得有些落伍和迟钝了。 AutoLayout可以完成所有原来Autoresizing Mask能完成的工作, 同时还能胜任一些原来无法完成的任务,其中包括:
 AutoLayout可以指定任意两个view的相对位置,而不需要像 Autoresizing Mask那样需要两个view在直系的view hierarchy
 AutoLayout不必须指定相等关系的约束,它可以指定非相等约 束(大于或者小于等);而Autoresizing Mask所能做的布局只 能是相等条件的
 AutoLayout可以指定约束的优先级,计算frame时将优先按照满 足优先级高的条件进行计算

AutoLayout的基本使用 
• 在创建约束之后,需要将其添加到作用的view上。
在添加时要注意目标view需要遵循以下规则:
• 1) 对于两个同层级view之间的约束关系,添加 到他们的父view

添加约束的规则(2
• 2) 对于两个不同层级view之间的约束关系,添加 到他们最近的共同父view

添加约束的规则(3
• 3) 对于有层次关系的两个view之间的约束关系, 添加到层次较高的父view 

创建约束(用手码必须保证所有的约束都成功) + (id)constraintWithItem:attribute:relatedBy:toItem:
attribute:multiplier:constant:! !
参数说明:! WithItem:要约束的对象! attribute:对象的布局属性! relatedBy:布局关系! toItem:参照对象!attribute:参照对象的布局属性! multiplier:乘数!constant:常数!
!

自动布局的核心公式!
Object1.property1 =(object2.property2 * multiplier)+ constant value!


• View.center.x = self.view.center.x * 1 + 0; • View.center.y = self.view.center.y * 1 + 0; 
添加和刷新约束 
 添加约束 -(void)addConstraint:(NSLayoutConstraint *)constraint
 刷新约束的改变 -setNeedsUpdateConstraints -layoutIfNeeded
[buttonsetTranslatesAutoresizingMaskIntoConstraints:NO];

测试演练4--使用代码添加约束 // 2.1 水平方向的约束 
NSLayoutConstraint *constraintX = [NSLayoutConstraintconstraintWithItem:buttonattribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.viewattribute:NSLayoutAttributeCenterX multiplier:1.0f constant: 0.0f];
!
[
self.view addConstraint:constraintX]; !
// 2.2 垂直方向的约束 
NSLayoutConstraint *constraintY = [NSLayoutConstraintconstraintWithItem:buttonattribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.viewattribute:NSLayoutAttributeCenterY multiplier:1.0f constant: 0.0f];
!
[
self.view addConstraint:constraintY]; 

Visual Format Language 可视格式语言 
• 这种语言是对视觉描述的一种抽象,例如:accept按钮在 cancel按钮右侧默认间距处,使用VFL描述的大概过程如下:
  
测试演练5--VFL演练(1
// 1. 创建三个按钮:topcenterbottom 
// 2. 三个按钮宽度为100 
// 3. 三个按钮距离屏幕右侧20 
// 4. bottom按钮距离屏幕底部20点,每个按钮纵向间距为20
NSDictionary *viewDict =NSDictionaryOfVariableBindings(top, center, bottom);
!
NSArray *consh1 = [NSLayoutConstraintconstraintsWithVisualFormat:@"H:[top(100)]-20-|" options:0 metrics:nilviews:viewDict];
 
NSArray *consv = [NSLayoutConstraintconstraintsWithVisualFormat:@"V:[top(40)]-20-[center(40)]-20- [bottom(40)]-20-|" options:0 metrics:nil views:viewDict];
...... 

测试演练6--VFL演练(2
// 1. 创建两个按钮:btn1btn2 // 2. 两个按钮宽度为100 // 3. btn1高度80点,btn2高度60 // 4. 两个按钮间距20点,btn2距离屏幕右侧20NSDictionary *dict2 = NSDictionaryOfVariableBindings(btn1, btn2);  
NSArray *consH = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[btn1(100)]-[btn2(100)]-20-|" options:0metrics:nil views:dict2];
 

VFL示例 
 [cancelButton(72)]-12-[acceptButton(50)] 
 取消按钮宽72point,accept按钮宽50point,它们之间间距12point 
 [wideView(>=60@700)] 
 wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为 1000,优先级越高的约束越先被满足) 
 V:[redBox][yellowBox(==redBox)] 
 竖直布局,先是一个redBox,其下方紧接一个宽度等于redBox宽度的 
yellowBox 
 H:|-[Find]-[FindNext]-[FindField(>=20)]-| 
 水平布局,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间 隔默认宽度;再之后是宽度不小于20FindField,它和FindNext以及父view右 边缘的间距都是默认宽度。(竖线“|" 表示superview的边缘) 

使用AutoLayout容易出现的错误 
 Ambiguous Layout 布局不能确定,即给出的约束条件无法唯一 确定一种布局,也就是约束条件不足,无法得到唯一的布局结 果。这种情况一般添加一些必要的约束或者调整优先级可以解 决 
 Unsatisfiable Constraints 无法满足约束,问题来源是有约束条 件互相冲突,因此无法同时满足,需要删掉一些约束 
 现在使用IB可以比较容易地完成复杂约束,在实际开发中很少 再会遇到遗漏或者多余约束情况的出现,有问题的约束条件将 直接在IB中得到错误或者警告 

视图动画 
• 需要记住的是:Core AnimationAuto Layout结合在一起产生视图动 画时,不要直接修改视图的frame一旦视图使用自动布局,意味着 已经将设置frame的责任交给了布局系统。你的干扰将造成怪异的行 为。
 一旦使用了自动布局,就要忘记Frame的概念!
• 此时应该使用:[myView layoutIfNeeded]; 
回顾 
• 随着iOS7的普及,会有越来越多的应用基于Storyboard开发 目前几乎所有的iOS开发的公司都面临着从iOS6iOS7的迁移及适配工
,基于AutoLayout开发的应用程序,迁移工作会相对简单
 AutoLayout随然没有直接定位坐标直观,但是熟悉之后,对屏幕适配 的支持将会非常方便,而且在开发过程中能够节约大量的代码,使得 程序员将更多的精力集中在程序功能的实现上,而不再是花费大量的 时间和精力去做屏幕适配的工作

© chenyilong. Powered by Postach.io


作者:
出处:http://www.cnblogs.com/ChenYilong/(点击RSS订阅)
本文版权归作者和博客园共有,欢迎转载,
但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/ChenYilong/p/3587197.html