一、概要

通过对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. 关于C# Math 处理奇进偶不进

    话说,最近一次系统维护 用JS读取导入Excel中的实验数据,出现被自动四舍五入.后来到客户现场听客户反馈  Excel实验数据要求 奇进偶不进. 关于 奇进偶不进 产生的由来:从统计学的角度,“奇进 ...

  2. ruby -- 问题解决(三)编码错误导致无法显示(1)

    从数据库中取得数据显示时报 incompatible character encodings: GBK and ASCII-8BIT 或 incompatible character encoding ...

  3. [SLAM] 02 Some algorithms of 3D reconstruction

    链接:http://www.zhihu.com/question/29885222/answer/100043031 首先一切建立在相机模型 x = kPX 上   x,X分别代表图片和空间中的二维三 ...

  4. spring源码分析之spring-web remoting模块概况及基本概念

    spring-web总体分为三部分:caucho.httpinvoker.jaxws,其总体构造图如下: uml结构: 先看看网上搜索到的上述实现的原理吧:Spring RMI,Hessian/Bur ...

  5. Direct3D11学习:(二)基本绘图概念和基本类型

    转载请注明出处:http://www.cnblogs.com/Ray1024   一.概述 在正式开始学习D3D11之前,我们必需首先学习必要的基础知识. 在这篇文章中,我们将介绍一下Direct3D ...

  6. BZOJ1003 物流运输 最短路+DP

    1003: [ZJOI2006]物流运输 Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条 ...

  7. [Tool] WireShark基本使用

    Wireshark(前称Ethereal)是一个网络封包分析软件. 在windows平台上,Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换. [参数设置]: 抓包参数(Cap ...

  8. MEF核心笔记(6)让 MEF 拥抱 AOP

    场景: 最近推荐同事在项目中使用起了 MEF,用其构建一个插件式的多人开发框架,因为该框架不是让我去设计了,所以对于 MEF 和 IOC 等概念不是很了解的同事,便会出现各种问题.接入 AOP 便是其 ...

  9. 使用BOM 的window对象属性打开新窗口

    ★  示例1 要求:弹出新窗口,并向新窗口写入动态HTML代码 代码 <buttononclick="btnOpen()">打开新窗口</button> & ...

  10. [新手学Java]使用beanUtils控制javabean

    使用BeanUtils设置/读取属性的值以及默认支持的自动转化: @Test //使用BeanUtils设置/读取属性的值以及自动转化 public void test1() throws Illeg ...