一、概要

通过对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. tcp为什要三次握手

    准备知识: 单工:信息只能单向传递.发送-->接收,单向,不能返回响应. 双工:指的是信息可双向发送. 全双工:信息可同时双向传递. 半双工:不能同时,单行道,一边传输完了,另一边才能发起传输. ...

  2. Java -- 获取当前日期、当月月初日期、月末日期

    Learn From:http://blog.csdn.net/sunhuwh/article/details/39161323 public class CalendarTest { public ...

  3. c# 无法引用自己创建的类库

    今个测试一个项目,居然无法引用自己创建的类库,我很费解,然后各种测试,修改修饰符,更改强类型,各种测试,最后无聊点开类库的属性  发现居然需要引用的项目与被引用的类库的框架不一样,修改了之后就可以正常 ...

  4. 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现

    概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现. ...

  5. [Node.js] 也说this

    原文地址:http://www.moye.me/2014/11/21/也说this/ 引子 Any sufficiently advanced technology is indistinguisha ...

  6. Hya.io – 基于 Web 的数字音频工作站

    Hya.io 是基于 Web 的音频应用程序,通过 Web MIDI ,音频合成器,音序以及大量的插件来支持硬件 MIDI .您可以添加插件到工作区,将其连接到路由音频,进行播放和实验. HYA 支持 ...

  7. 资料下载:敏捷个人的成长思考.pptx(第1次线下活动2011.04)

    本文挪至 http://www.zhoujingen.cn/blog/629.html PDF下载地址:http://down.51cto.com/data/207112 推荐:你可能需要的在线电子书 ...

  8. IOS开发UI基础UIControl事件

    UIControl事件1.UIControlEventTouchDown单点触摸按下事件:用户点触屏幕,或者又有新手指落下的时候. 2.UIControlEventTouchDownRepeat多点触 ...

  9. Scrum4.0+5.0 数独游戏

    1.题目: 1.准备看板. 形式参考图4. 2.任务认领,并把认领人标注在看板上的任务标签上. 先由个人主动领任务,PM根据具体情况进行任务的平衡. 然后每个人都着手实现自己的任务. 3.为了团队合作 ...

  10. .Net配置文件——反射+配置文件存储类型实例

    配置文件+反射确实去除了选择语句的繁琐,带来了优美的赶脚! 首先改进了一下类(接上文): ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ...