iOS开发~UI布局(三)深入理解autolayout
通过对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)最基本的约束实现方式
- <span style="font-size:12px;">- (void)viewDidLoad {
- [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- self.view.translatesAutoresizingMaskIntoConstraints =NO;
- UIView *newView = [UIView new];
- newView.backgroundColor = [UIColor greenColor];
- [self.view addSubview:newView];
- newView.translatesAutoresizingMaskIntoConstraints =NO;
- NSLayoutConstraint *constraint = nil;
- constraint = [NSLayoutConstraint constraintWithItem:newView
- attribute:NSLayoutAttributeLeading
- relatedBy:NSLayoutRelationEqual
- toItem:self.view
- attribute:NSLayoutAttributeLeading
- multiplier:1.0f
- constant:20];
- [self.view addConstraint:constraint];
- constraint = [NSLayoutConstraint constraintWithItem:newView
- attribute:NSLayoutAttributeTrailing
- relatedBy:NSLayoutRelationEqual
- toItem:self.view
- attribute:NSLayoutAttributeTrailing
- multiplier:1.0f
- constant:-20];
- [self.view addConstraint:constraint];
- constraint = [NSLayoutConstraint constraintWithItem:newView
- attribute:NSLayoutAttributeTop
- relatedBy:NSLayoutRelationEqual
- toItem:self.view
- attribute:NSLayoutAttributeTop
- multiplier:1.0f
- constant:20];
- [self.view addConstraint:constraint];
- constraint = [NSLayoutConstraint constraintWithItem:newView
- attribute:NSLayoutAttributeBottom
- relatedBy:NSLayoutRelationEqual
- toItem:self.view
- attribute:NSLayoutAttributeBottom
- multiplier:1.0f
- constant:-20];
- [self.view addConstraint:constraint];
- }</span>
(2)特殊格式化语言的约束实现方式
- <span style="font-size:12px;">- (void)viewDidLoad {
- [super viewDidLoad];
- self.view.translatesAutoresizingMaskIntoConstraints =NO;
- UIView *newView = [UIView new];
- newView.backgroundColor = [UIColor greenColor];
- [self.view addSubview:newView];
- newView.translatesAutoresizingMaskIntoConstraints =NO;
- NSMutableArray *constraintArray = [NSMutableArray array];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[newView]-20-|"
- options:0
- metrics:nil
- views:NSDictionaryOfVariableBindings(newView, self.view)]];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[newView]-20-|"
- options:0
- metrics:nil
- views:NSDictionaryOfVariableBindings(newView, self.view)]];
- [self.view addConstraints:constraintArray];
- }</span>
(3)第三方UIView-AutoLayout
- <span style="font-size:12px;">- (void)viewDidLoad {
- [super viewDidLoad];
- self.view.translatesAutoresizingMaskIntoConstraints =NO;
- UIView *newView = [UIView new];
- newView.backgroundColor = [UIColor greenColor];
- [self.view addSubview:newView];
- newView.translatesAutoresizingMaskIntoConstraints =NO;
- [newView autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:20.0f];
- [newView autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:20.0f];
- [newView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:20.0f];
- [newView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:20.0f];
- }</span>
以上3种方式都实现了我们想要的效果,看来代码实现autolayout也不是那么复杂!
例子2:通过上边例子我们实现一个简单的UI布局,下面来一个稍微复杂点的,把上一篇中提到3个view布局的那个例子用代码布局实现一下,但难度有所增加,当size class切换的时候,页面布局发生相应的改变,效果如图:
首先初始化3个View:
- <span style="font-size:12px;">- (UIView *) alView {
- UIView *newView = [UIView new];
- newView.translatesAutoresizingMaskIntoConstraints =NO;
- return newView;
- }
- UIView *greenView = [self alView];
- greenView.backgroundColor = [UIColor greenColor];
- [self.view addSubview:greenView];
- UIView *yellowView = [self alView];
- yellowView.backgroundColor = [UIColor yellowColor];
- [self.view addSubview:yellowView];
- UIView *blueView = [self alView];
- blueView.backgroundColor = [UIColor blueColor];
- [self.view addSubview:blueView];</span>
接下来适配竖屏的约束:
- <span style="font-size:12px;">- (NSMutableArray *) portraitConstraints:(UIView *)greenView :(UIView *)yellowView :(UIView *)blueView
- {
- NSMutableArray *constraintArray = [NSMutableArray array];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint
- constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|" options:0 metrics:nil
- views:NSDictionaryOfVariableBindings(greenView, yellowView)]];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint
- constraintsWithVisualFormat:@"V:|-20-[greenView]-20-[blueView(==greenView)]-20-|" options:0 metrics:nil
- views:NSDictionaryOfVariableBindings(greenView, blueView)]];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint
- constraintsWithVisualFormat:@"V:|-20-[yellowView]-20-[blueView(==yellowView)]-20-|" options:0 metrics:nil
- views:NSDictionaryOfVariableBindings(yellowView, blueView)]];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint
- constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|" options:0 metrics:nil
- views:NSDictionaryOfVariableBindings(blueView)]];
- return constraintArray;
- }</span>
然后横屏的约束:
- <span style="font-size:12px;">- (NSMutableArray *) landscapeConstraints:(UIView *)greenView :(UIView *)yellowView :(UIView *)blueView
- {
- NSMutableArray *constraintArray = [NSMutableArray array];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint
- constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|" options:0 metrics:nil
- views:NSDictionaryOfVariableBindings(greenView, yellowView)]];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint
- constraintsWithVisualFormat:@"V:|-20-[blueView]-20-[greenView(==blueView)]-20-|" options:0 metrics:nil
- views:NSDictionaryOfVariableBindings(greenView, blueView)]];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint
- constraintsWithVisualFormat:@"V:|-20-[blueView]-20-[yellowView(==blueView)]-20-|" options:0 metrics:nil
- views:NSDictionaryOfVariableBindings(yellowView, blueView)]];
- [constraintArray addObjectsFromArray:[NSLayoutConstraint
- constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|" options:0 metrics:nil
- views:NSDictionaryOfVariableBindings(blueView)]];
- return constraintArray;
- }</span>
最后还要处理屏幕旋转:
- <span style="font-size:12px;">- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
- withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
- {
- [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
- [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) {
- if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
- NSLog(@"%s----%d", __FUNCTION__, __LINE__);
- [self.view removeConstraints:self.view.constraints];
- [self.view addConstraints:[self landscapeConstraints:self.greenView_ :self.yellowView_ :self.blueView_]];
- } else {
- NSLog(@"%s----%d", __FUNCTION__, __LINE__);
- [self.view removeConstraints:self.view.constraints];
- [self.view addConstraints:[self portraitConstraints:self.greenView_ :self.yellowView_ :self.blueView_]];
- }
- [self.view setNeedsLayout];
- } completion:nil];
- }</span>
这样就实现了我们预期的效果,总结下来,auotlayout就是给view添加足够的约束,让view系统可以根据约束来计算出一个view的frame。动手练习一下吧!
2、view动画在autolayout实现
当布局发生改变时,相当于对子view进行重新布局,而子view重新布局调用 layoutIfNeeded,所以动画可以这样实现:
- <span style="font-size:12px;">- (void)animateConstraints
- {
- [UIView animateWithDuration:0.5 animations:^{
- [self.view layoutIfNeeded];
- }];
- }</span>
Github上已经有Demo了!
3、autolayout有没有局限性和解决不了的问题?兼容性怎么样?效率怎么样?
autolayout对view transforms支持的不好,这里有帖子详细描述了这个问题。
至于兼容性,只从iOS6就已经提出了autolayout的概念,现在iOS5系统不是很多了,甚至iOS6系统都已经升级为iOS7,未来一段时间大部分用户应该是使用iOS7和iOS8系统,所以兼容性问题不会太大,但size class是iOS8才有的概念,所以还有有一定的适配工作量。
效率话题这里有提到,有时间再细研究。
结束语:时间和体力总是有限的,标题是autolayout详解,可想达到详解还需要更多的时间去实践和总结,还有一些细节没有体现出来:
例如:
- <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的更多相关文章
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布 ...
- iOS开发UI篇—iOS开发中三种简单的动画设置
iOS开发UI篇—iOS开发中三种简单的动画设置 [在ios开发中,动画是廉价的] 一.首尾式动画 代码示例: // beginAnimations表示此后的代码要“参与到”动画中 [UIView b ...
- iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局
iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 一.项目文件结构和plist文件 二.实现效果 三.代码示例 1.没有使用配套的类,而是直接使用xib文 ...
- iOS开发-UI 从入门到精通(三)
iOS开发-UI 从入门到精通(三)是对 iOS开发-UI 从入门到精通(一)知识点的综合练习,搭建一个简单地登陆界面,增强实战经验,为以后做开发打下坚实的基础! ※在这里我们还要强调一下,开发环境和 ...
- iOS开发UI篇—Quartz2D简单使用(三)
iOS开发UI篇—Quartz2D简单使用(三) 一.通过slider控制圆的缩放 1.实现过程 新建一个项目,新建一个继承自UIview的类,并和storyboard中自定义的view进行关联. 界 ...
- iOS开发UI篇—UIScrollView控件介绍
iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...
- iOS开发UI篇—核心动画简介
转自:http://www.cnblogs.com/wendingding/p/3801036.html iOS开发UI篇—核心动画简介 一.简单介绍 Core Animation,中文翻译为核心动画 ...
- iOS开发UI篇—手写控件,frame,center和bounds属性
iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4 ...
- iOS开发UI篇—九宫格坐标计算
iOS开发UI篇—九宫格坐标计算 一.要求 完成下面的布局 二.分析 寻找左边的规律,每一个uiview的x坐标和y坐标. 三.实现思路 (1)明确每一块用得是什么view (2)明确每个view之间 ...
- iOS开发UI篇—xib的简单使用
iOS开发UI篇—xib的简单使用 一.简单介绍 xib和storyboard的比较,一个轻量级一个重量级. 共同点: 都用来描述软件界面 都用Interface Builder工具来编辑 不同点: ...
随机推荐
- 白话Redis与Memcached区别
如果简单地比较Redis与Memcached的区别,外在的区别是: 1 Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储. 2 Redis ...
- NGUI 动态添加控件
本文链接地址: Unity3D NGUI动态创建按钮 本例仅以熟悉NGUI组件功能为目的,想快捷简便的创建按钮或其它游戏物体请参考 “Unity3D 动态实例化Prefab” 以动态创建服务器列表为例 ...
- win7中的画图
下午做一个图像篡改定位实验,在win7下对图像进行修改,然后通过其最低位判断篡改位置. 程序如何都调试不出来.反复简化程序,发现win7中的画图对图像存在优化. 当更改图像后,会自动调整当前图像的显示 ...
- supervisor 安装 配置 及 使用
supervisor是微软官方推荐的一个工具,传送门, 所以我们也使用这个工具来管理我们的asp.net core应用进程 服务器环境:ubuntu14.04 x64 安装 apt-get ...
- Frame - 快速创建高品质的 Web 应用原型
Frame 是一个让你够能够快速创建高品质的网站或应用程序产品原型的工具.你上传的图片将被包裹在真实的设备环境中.它是一个用于创建宣传资料的专业工具.Frame 完全免费供给商业和个人使用.他们也正探 ...
- 十分钟搞懂什么是CGI
原文:CGI Made Really Easy,在翻译的过程中,我增加了一些我在学习过程中找到的更合适的资料,和自己的一些理解.不能算是严格的翻译文章,应该算是我的看这篇文章的过程的随笔吧. CGI真 ...
- 将form表单元素转为实体对象 或集合 -ASP.NET C#
简介: 做WEBFROM开发的同学都知道后台接收参数非常麻烦 虽然MVC中可以将表单直接转为集实,但不支持表单转为 LIST<T>这种集合 单个对象的用法: 表单: <input n ...
- MyBatis魔法堂:ResultMap详解
一.前言 MyBatis是基于“数据库结构不可控”的思想建立的,也就是我们希望数据库遵循第三范式或BCNF,但实际事与愿违,那么结果集映射就是MyBatis为我们提供这种理想与现实间转换的手段了, ...
- awk引用外部变量及调用系统命令方法
目标:想用awk与scp命令批量传送文件 前提:先搭好主机间的免密登陆环境(参考:http://www.cnblogs.com/tankaixiong/p/4172942.html) 实现脚本方法: ...
- [Solution] DI原理解析及Castle、Unity框架使用
本节目录 DI介绍 DI基本原理 DI框架 Castle Windsor Unity Autofac Spring.Net DI介绍 控制反转(Inversion of Control,英文缩写为Io ...