一、概要

通过对iOS8界面布局的学习和总结,发现autolayout才是主角,autolayout是iOS6引入的新特性,当时还粗浅的学习了下,可是没有真正应用到项目中。随着iOS设备尺寸逐渐碎片化,纯粹的hard code方式UI布局将会走向死角,而autoresizing方式也有其局限性,所以无论如何autolayout都将成为UI布局的重要方式。

前两篇以发烧友心态对iOS8界面布局的主要元素size class和autolayout进行了探索,发现要完全掌握autolayout需要大量的时间去实践总结。所以深入思考autolayout是很有必要的。你可能有和我同样的疑问,如下:

1、以后一律使用autolayout吗?除了在storyboard中使用autolayout,代码方式autolayout如何使用?

2、好像忽略了一个重要问题,就是view动画在autolayout如何实现?

3、autolayout有没有局限性和解决不了的问题?兼容性怎么样?效率怎么样?

4、……

二、研究开始

1、直接说以后都应该使用storyboard+autolayout感觉是不负责的说法,读了好多网络的帖子,最后总结如下情况使用autolayout会有帮助:

a 当需要展示的内容很多并且尺寸不固定;

b 程序需支持屏幕旋转(主要是iPad程序,iPhone程序横屏的场景有点非主流);

c 程序通用于iPhone和iPad;

但storyboard中使用autolayout有利有弊,好处当然是可视化,实现简单功能很节省时间,但也有弊端,例如不小心移动一个控件就会让弄乱那些约束。抛开storyboard而使用autolayout,就需要代码定义约束了,而且代码量也不是很大。当app中一些view的出现时根据网络数据来决定的时候,代码方式可能更合适。

先看一个简单的Demo:

例子1:新建一个Single View Application template项目Demo4,在rootView上添加一个绿颜色的view,使新添加的view四个边距离superView四边20点宽

效果如图:

使用storyboard来实现这个效果很简单,选中绿色view,然后添加4个相对于superview的边界约束,约束的数值设置为20,然后Update Frame就可以了,因为不区分iOS设备,所以size class可以设置为默认的wAny hAny。Demo下载

接下来使用代码来实现UI布局,目前有3种方法可以使用:(1)最基本的约束实现方式;(2)特殊格式化语言的约束实现方式;(3)第三方UIView-AutoLayout

(1)最基本的约束实现方式

  1. <span style="font-size:12px;">- (void)viewDidLoad {
  2. [super viewDidLoad];
  3. // Do any additional setup after loading the view, typically from a nib.
  4. self.view.translatesAutoresizingMaskIntoConstraints =NO;
  5. UIView *newView = [UIView new];
  6. newView.backgroundColor = [UIColor greenColor];
  7. [self.view addSubview:newView];
  8. newView.translatesAutoresizingMaskIntoConstraints =NO;
  9. NSLayoutConstraint *constraint = nil;
  10. constraint = [NSLayoutConstraint constraintWithItem:newView
  11. attribute:NSLayoutAttributeLeading
  12. relatedBy:NSLayoutRelationEqual
  13. toItem:self.view
  14. attribute:NSLayoutAttributeLeading
  15. multiplier:1.0f
  16. constant:20];
  17. [self.view addConstraint:constraint];
  18. constraint = [NSLayoutConstraint constraintWithItem:newView
  19. attribute:NSLayoutAttributeTrailing
  20. relatedBy:NSLayoutRelationEqual
  21. toItem:self.view
  22. attribute:NSLayoutAttributeTrailing
  23. multiplier:1.0f
  24. constant:-20];
  25. [self.view addConstraint:constraint];
  26. constraint = [NSLayoutConstraint constraintWithItem:newView
  27. attribute:NSLayoutAttributeTop
  28. relatedBy:NSLayoutRelationEqual
  29. toItem:self.view
  30. attribute:NSLayoutAttributeTop
  31. multiplier:1.0f
  32. constant:20];
  33. [self.view addConstraint:constraint];
  34. constraint = [NSLayoutConstraint constraintWithItem:newView
  35. attribute:NSLayoutAttributeBottom
  36. relatedBy:NSLayoutRelationEqual
  37. toItem:self.view
  38. attribute:NSLayoutAttributeBottom
  39. multiplier:1.0f
  40. constant:-20];
  41. [self.view addConstraint:constraint];
  42. }</span>

(2)特殊格式化语言的约束实现方式

  1. <span style="font-size:12px;">- (void)viewDidLoad {
  2. [super viewDidLoad];
  3. self.view.translatesAutoresizingMaskIntoConstraints =NO;
  4. UIView *newView = [UIView new];
  5. newView.backgroundColor = [UIColor greenColor];
  6. [self.view addSubview:newView];
  7. newView.translatesAutoresizingMaskIntoConstraints =NO;
  8. NSMutableArray *constraintArray = [NSMutableArray array];
  9. [constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[newView]-20-|"
  10. options:0
  11. metrics:nil
  12. views:NSDictionaryOfVariableBindings(newView, self.view)]];
  13. [constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[newView]-20-|"
  14. options:0
  15. metrics:nil
  16. views:NSDictionaryOfVariableBindings(newView, self.view)]];
  17. [self.view addConstraints:constraintArray];
  18. }</span>

(3)第三方UIView-AutoLayout

  1. <span style="font-size:12px;">- (void)viewDidLoad {
  2. [super viewDidLoad];
  3. self.view.translatesAutoresizingMaskIntoConstraints =NO;
  4. UIView *newView = [UIView new];
  5. newView.backgroundColor = [UIColor greenColor];
  6. [self.view addSubview:newView];
  7. newView.translatesAutoresizingMaskIntoConstraints =NO;
  8. [newView autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:20.0f];
  9. [newView autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:20.0f];
  10. [newView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:20.0f];
  11. [newView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:20.0f];
  12. }</span>

以上3种方式都实现了我们想要的效果,看来代码实现autolayout也不是那么复杂!

例子2:通过上边例子我们实现一个简单的UI布局,下面来一个稍微复杂点的,把上一篇中提到3个view布局的那个例子用代码布局实现一下,但难度有所增加,当size class切换的时候,页面布局发生相应的改变,效果如图:

            

首先初始化3个View:

  1. <span style="font-size:12px;">- (UIView *) alView {
  2. UIView *newView = [UIView new];
  3. newView.translatesAutoresizingMaskIntoConstraints =NO;
  4. return newView;
  5. }
  6. UIView *greenView = [self alView];
  7. greenView.backgroundColor = [UIColor greenColor];
  8. [self.view addSubview:greenView];
  9. UIView *yellowView = [self alView];
  10. yellowView.backgroundColor = [UIColor yellowColor];
  11. [self.view addSubview:yellowView];
  12. UIView *blueView = [self alView];
  13. blueView.backgroundColor = [UIColor blueColor];
  14. [self.view addSubview:blueView];</span>

接下来适配竖屏的约束:

  1. <span style="font-size:12px;">- (NSMutableArray *) portraitConstraints:(UIView *)greenView :(UIView *)yellowView :(UIView *)blueView
  2. {
  3. NSMutableArray *constraintArray = [NSMutableArray array];
  4. [constraintArray addObjectsFromArray:[NSLayoutConstraint
  5. constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|" options:0 metrics:nil
  6. views:NSDictionaryOfVariableBindings(greenView, yellowView)]];
  7. [constraintArray addObjectsFromArray:[NSLayoutConstraint
  8. constraintsWithVisualFormat:@"V:|-20-[greenView]-20-[blueView(==greenView)]-20-|" options:0 metrics:nil
  9. views:NSDictionaryOfVariableBindings(greenView, blueView)]];
  10. [constraintArray addObjectsFromArray:[NSLayoutConstraint
  11. constraintsWithVisualFormat:@"V:|-20-[yellowView]-20-[blueView(==yellowView)]-20-|" options:0 metrics:nil
  12. views:NSDictionaryOfVariableBindings(yellowView, blueView)]];
  13. [constraintArray addObjectsFromArray:[NSLayoutConstraint
  14. constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|" options:0 metrics:nil
  15. views:NSDictionaryOfVariableBindings(blueView)]];
  16. return constraintArray;
  17. }</span>

然后横屏的约束:

  1. <span style="font-size:12px;">- (NSMutableArray *) landscapeConstraints:(UIView *)greenView :(UIView *)yellowView :(UIView *)blueView
  2. {
  3. NSMutableArray *constraintArray = [NSMutableArray array];
  4. [constraintArray addObjectsFromArray:[NSLayoutConstraint
  5. constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|" options:0 metrics:nil
  6. views:NSDictionaryOfVariableBindings(greenView, yellowView)]];
  7. [constraintArray addObjectsFromArray:[NSLayoutConstraint
  8. constraintsWithVisualFormat:@"V:|-20-[blueView]-20-[greenView(==blueView)]-20-|" options:0 metrics:nil
  9. views:NSDictionaryOfVariableBindings(greenView, blueView)]];
  10. [constraintArray addObjectsFromArray:[NSLayoutConstraint
  11. constraintsWithVisualFormat:@"V:|-20-[blueView]-20-[yellowView(==blueView)]-20-|" options:0 metrics:nil
  12. views:NSDictionaryOfVariableBindings(yellowView, blueView)]];
  13. [constraintArray addObjectsFromArray:[NSLayoutConstraint
  14. constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|" options:0 metrics:nil
  15. views:NSDictionaryOfVariableBindings(blueView)]];
  16. return constraintArray;
  17. }</span>

最后还要处理屏幕旋转:

  1. <span style="font-size:12px;">- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
  2. withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
  3. {
  4. [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
  5. [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) {
  6. if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
  7. NSLog(@"%s----%d", __FUNCTION__, __LINE__);
  8. [self.view removeConstraints:self.view.constraints];
  9. [self.view addConstraints:[self landscapeConstraints:self.greenView_ :self.yellowView_ :self.blueView_]];
  10. } else {
  11. NSLog(@"%s----%d", __FUNCTION__, __LINE__);
  12. [self.view removeConstraints:self.view.constraints];
  13. [self.view addConstraints:[self portraitConstraints:self.greenView_ :self.yellowView_ :self.blueView_]];
  14. }
  15. [self.view setNeedsLayout];
  16. } completion:nil];
  17. }</span>

这样就实现了我们预期的效果,总结下来,auotlayout就是给view添加足够的约束,让view系统可以根据约束来计算出一个view的frame。动手练习一下吧!

2、view动画在autolayout实现

当布局发生改变时,相当于对子view进行重新布局,而子view重新布局调用 layoutIfNeeded,所以动画可以这样实现:

  1. <span style="font-size:12px;">- (void)animateConstraints
  2. {
  3. [UIView animateWithDuration:0.5 animations:^{
  4. [self.view layoutIfNeeded];
  5. }];
  6. }</span>

Github上已经有Demo了!

3、autolayout有没有局限性和解决不了的问题?兼容性怎么样?效率怎么样?

autolayout对view transforms支持的不好,这里有帖子详细描述了这个问题。

至于兼容性,只从iOS6就已经提出了autolayout的概念,现在iOS5系统不是很多了,甚至iOS6系统都已经升级为iOS7,未来一段时间大部分用户应该是使用iOS7和iOS8系统,所以兼容性问题不会太大,但size class是iOS8才有的概念,所以还有有一定的适配工作量。

效率话题这里有提到,有时间再细研究。

结束语:时间和体力总是有限的,标题是autolayout详解,可想达到详解还需要更多的时间去实践和总结,还有一些细节没有体现出来:

例如:

  1. <span style="font-size:12px;">[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[newView]-20-|"options:0 metrics:nil views:NSDictionaryOfVariableBindings(newView, self.view)]</span>

1、这其中各个参数的含义,另外约束还有个优先级的概念

2、@"H:|-20-[newView]-20-|" 这种可视化布局字符串的含义等等,有空再补充了!

iOS开发~UI布局(三)深入理解autolayout的更多相关文章

  1. ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

    本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布 ...

  2. iOS开发UI篇—iOS开发中三种简单的动画设置

    iOS开发UI篇—iOS开发中三种简单的动画设置 [在ios开发中,动画是廉价的] 一.首尾式动画 代码示例: // beginAnimations表示此后的代码要“参与到”动画中 [UIView b ...

  3. iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局

    iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 一.项目文件结构和plist文件 二.实现效果 三.代码示例 1.没有使用配套的类,而是直接使用xib文 ...

  4. iOS开发-UI 从入门到精通(三)

    iOS开发-UI 从入门到精通(三)是对 iOS开发-UI 从入门到精通(一)知识点的综合练习,搭建一个简单地登陆界面,增强实战经验,为以后做开发打下坚实的基础! ※在这里我们还要强调一下,开发环境和 ...

  5. iOS开发UI篇—Quartz2D简单使用(三)

    iOS开发UI篇—Quartz2D简单使用(三) 一.通过slider控制圆的缩放 1.实现过程 新建一个项目,新建一个继承自UIview的类,并和storyboard中自定义的view进行关联. 界 ...

  6. iOS开发UI篇—UIScrollView控件介绍

    iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...

  7. iOS开发UI篇—核心动画简介

    转自:http://www.cnblogs.com/wendingding/p/3801036.html iOS开发UI篇—核心动画简介 一.简单介绍 Core Animation,中文翻译为核心动画 ...

  8. iOS开发UI篇—手写控件,frame,center和bounds属性

    iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4 ...

  9. iOS开发UI篇—九宫格坐标计算

    iOS开发UI篇—九宫格坐标计算 一.要求 完成下面的布局 二.分析 寻找左边的规律,每一个uiview的x坐标和y坐标. 三.实现思路 (1)明确每一块用得是什么view (2)明确每个view之间 ...

  10. iOS开发UI篇—xib的简单使用

    iOS开发UI篇—xib的简单使用 一.简单介绍 xib和storyboard的比较,一个轻量级一个重量级. 共同点: 都用来描述软件界面 都用Interface Builder工具来编辑 不同点: ...

随机推荐

  1. epoll源码实现分析[整理]

    epoll用法回顾 先简单回顾下如何使用C库封装的3个epoll相关的系统调用.更详细的用法参见http://www.cnblogs.com/apprentice89/archive/2013/05/ ...

  2. SQL:一句话删除重复的数据

    --构造原始数据 )) --插入数据 INSERT INTO #T (N)VALUES ('A') --方式一:一句话删除重复数据(无主键) --方式二:采用CTQ,with的写法删除 ;

  3. boi剖析 - 基于webpack的css sprites实现方案

    本文是58到家前端工程化集成解决方案boi的博文系列之一.boi是基于webpack打造的一站式前端工程化解决方案,现已开源Github. 作为前端构建工具不可或缺的一个环节,自动生成css spri ...

  4. Oracle 11g 安全加固

    1.安全加固的检查方向 2.安全加固检查safeCheck.sh 3.安全加固执行safeExec.sh 1.安全加固的检查方向 1.1.sysdba用户远程登录限制(查看Oracle登录认证方式) ...

  5. Marvel – 将图像和源文件转换成互动,共享的原型

    Marvel 是一款非常简单的工具,将图像和设计源文件转换成互动,共享的原型,无需任何编码.原型可以通过点击几下鼠标就创建出来,能工作在任何设备上的浏览器,包括移动设备,台式机.Marvel 的一个特 ...

  6. [python实用代码片段]python获取当前时间的前一天,前一周,前一个月

    python获取当前时间的前一天,前一周,前一个月. 实用python的datetime.timedelta方法,避免了有的月份是30和31等不同的情况. 获取前一个月的时间,方法实现:首先datet ...

  7. Android下拉刷新底部操作栏的隐藏问题

    最近自己编写下拉刷新的时候,发现了一个问题,就是有一个需求是这样的:要求页面中是一个Tab切换界面,一个界面有底部操作栏,不可下拉刷新,另一个界面没有底部操作栏,但可以下拉刷新. 按照平常的做法,我在 ...

  8. Sql Server来龙去脉系列 必须知道的权限控制核心篇

    最近写了<Sql Server来龙去脉系列  必须知道的权限控制基础篇>,感觉反响比较大.这可能也说明了很多程序猿对数据库权限控制方面比较感兴趣,或者某些技术点了解的没有很透彻. 有些人看 ...

  9. JdbcTemplate使用总结

    Spring JdbcTemplate 在数据库的操作中,每个业务方法都要得到连接,开启事务,提交事务,回滚,关闭连接等,我们可以把这些做成一个模版,这样,在业务代码中只需要关注业务逻辑即可. MyJ ...

  10. Java集合Iterator迭代器的实现

    一.迭代器概述 1.什么是迭代器? 在Java中,有很多的数据容器,对于这些的操作有很多的共性.Java采用了迭代器来为各种容器提供了公共的操作接口.这样使得对容器的遍历操作与其具体的底层实现相隔离, ...