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,不论在旋转 屏幕或是更换设备(iPad、iPad mini、iPhone 4或者是iPhone5)的时 候,始终还在底部之上10像素居中的位置,不会发生变化
• 使用约束条件来描述布局,view的frame会依据这些约束来进行计算
测试演练2--在Storyboard中使用自动布局
• 在Storyboard中为一个屏幕居中的按钮添加水平居中和垂直居中的布
局约束
• 经过运行测试不难发现,添加了自动布局之后,在不同分辨率的设备 以及不同的版本的设备上运行时该按钮始终会保持在屏幕中间
测试演练3--在Storyboard中使用自动布局
• 以前一演练为基础,分别在垂直方向上,上下各放置间距20点的两个
按钮
• 经过运行测试不难发现,在不同分辨率的设备以及不同的版本的设备 上运行时该按钮始终会保持在屏幕中间,而且无需编写任何的代码!
AutoLayout和Autoresizing 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. 创建三个按钮:top、center、bottom
// 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. 创建两个按钮:btn1、btn2 // 2. 两个按钮宽度为100点 // 3. btn1高度80点,btn2高度60点 // 4. 两个按钮间距20点,btn2距离屏幕右侧20点NSDictionary *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间 隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右 边缘的间距都是默认宽度。(竖线“|" 表示superview的边缘)
使用AutoLayout容易出现的错误
• Ambiguous Layout 布局不能确定,即给出的约束条件无法唯一 确定一种布局,也就是约束条件不足,无法得到唯一的布局结 果。这种情况一般添加一些必要的约束或者调整优先级可以解 决
• Unsatisfiable Constraints 无法满足约束,问题来源是有约束条 件互相冲突,因此无法同时满足,需要删掉一些约束
• 现在使用IB可以比较容易地完成复杂约束,在实际开发中很少 再会遇到遗漏或者多余约束情况的出现,有问题的约束条件将 直接在IB中得到错误或者警告
视图动画
• 需要记住的是:Core Animation和Auto Layout结合在一起产生视图动 画时,不要直接修改视图的frame。一旦视图使用自动布局,意味着 已经将设置frame的责任交给了布局系统。你的干扰将造成怪异的行 为。
• 一旦使用了自动布局,就要忘记Frame的概念!
• 此时应该使用:[myView layoutIfNeeded];
回顾
• 随着iOS7的普及,会有越来越多的应用基于Storyboard开发• 目前几乎所有的iOS开发的公司都面临着从iOS6到iOS7的迁移及适配工
作,基于AutoLayout开发的应用程序,迁移工作会相对简单
• AutoLayout随然没有直接定位坐标直观,但是熟悉之后,对屏幕适配 的支持将会非常方便,而且在开发过程中能够节约大量的代码,使得 程序员将更多的精力集中在程序功能的实现上,而不再是花费大量的 时间和精力去做屏幕适配的工作
© chenyilong. Powered by Postach.io
作者:
出处:http://www.cnblogs.com/ChenYilong/(点击RSS订阅)
本文版权归作者和博客园共有,欢迎转载,
但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。