iOS8开发~UI布局(三)深刻理解autolayout

1、概要

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

前两篇以发烧友心态对iOS8界面布局的主要元素size class和autolayout进行了探索,发现要彻底掌握autolayout须要大量的时间去实践总结。因此深刻思考autolayout是颇有必要的。你可能有和我一样的疑问,以下:git

一、之后一概使用autolayout吗?除了在storyboard中使用autolayout,代码方式autolayout如何使用?github

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

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

四、……app

2、研究开始ide

一、直接说之后都应该使用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)最基本的约束实现方式

 

[objc]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
 
  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.       
  6.     UIView *newView = [UIView new];  
  7.     newView.backgroundColor = [UIColor greenColor];  
  8.     [self.view addSubview:newView];  
  9.       
  10.     newView.translatesAutoresizingMaskIntoConstraints =NO;  
  11.       
  12.     NSLayoutConstraint *constraint = nil;  
  13.       
  14.     constraint = [NSLayoutConstraint constraintWithItem:newView  
  15.                                               attribute:NSLayoutAttributeLeading  
  16.                                               relatedBy:NSLayoutRelationEqual  
  17.                                                  toItem:self.view  
  18.                                               attribute:NSLayoutAttributeLeading  
  19.                                              multiplier:1.0f  
  20.                                                constant:20];  
  21.     [self.view addConstraint:constraint];  
  22.       
  23.     constraint = [NSLayoutConstraint constraintWithItem:newView  
  24.                                               attribute:NSLayoutAttributeTrailing  
  25.                                               relatedBy:NSLayoutRelationEqual  
  26.                                                  toItem:self.view  
  27.                                               attribute:NSLayoutAttributeTrailing  
  28.                                              multiplier:1.0f  
  29.                                                constant:-20];  
  30.     [self.view addConstraint:constraint];  
  31.       
  32.     constraint = [NSLayoutConstraint constraintWithItem:newView  
  33.                                               attribute:NSLayoutAttributeTop  
  34.                                               relatedBy:NSLayoutRelationEqual  
  35.                                                  toItem:self.view  
  36.                                               attribute:NSLayoutAttributeTop  
  37.                                              multiplier:1.0f  
  38.                                                constant:20];  
  39.     [self.view addConstraint:constraint];  
  40.       
  41.     constraint = [NSLayoutConstraint constraintWithItem:newView  
  42.                                               attribute:NSLayoutAttributeBottom  
  43.                                               relatedBy:NSLayoutRelationEqual  
  44.                                                  toItem:self.view  
  45.                                               attribute:NSLayoutAttributeBottom  
  46.                                              multiplier:1.0f  
  47.                                                constant:-20];  
  48.     [self.view addConstraint:constraint];  
  49.       
  50. }</span>  

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

 

 

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

(3)第三方 UIView-AutoLayout

 

 

[objc]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
 
  1. <span style="font-size:12px;">- (void)viewDidLoad {  
  2.     [super viewDidLoad];  
  3.     self.view.translatesAutoresizingMaskIntoConstraints =NO;  
  4.       
  5.     UIView *newView = [UIView new];  
  6.     newView.backgroundColor = [UIColor greenColor];  
  7.     [self.view addSubview:newView];  
  8.     newView.translatesAutoresizingMaskIntoConstraints =NO;  
  9.       
  10.     [newView autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:20.0f];  
  11.     [newView autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:20.0f];  
  12.     [newView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:20.0f];  
  13.     [newView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:20.0f];  
  14. }</span>  

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

 

 

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

            

首先初始化3个View:

 

[objc]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
 
  1. <span style="font-size:12px;">- (UIView *) alView {  
  2.     UIView *newView = [UIView new];  
  3.     newView.translatesAutoresizingMaskIntoConstraints =NO;  
  4.       
  5.     return newView;  
  6. }  
  7. UIView *greenView = [self alView];  
  8. greenView.backgroundColor = [UIColor greenColor];  
  9. [self.view addSubview:greenView];  
  10. UIView *yellowView = [self alView];  
  11. yellowView.backgroundColor = [UIColor yellowColor];  
  12. [self.view addSubview:yellowView];  
  13. UIView *blueView = [self alView];  
  14. blueView.backgroundColor = [UIColor blueColor];  
  15. [self.view addSubview:blueView];</span>  

 

接下来适配竖屏的约束:

 

[objc]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
 
  1. <span style="font-size:12px;">- (NSMutableArray *) portraitConstraints:(UIView *)greenView :(UIView *)yellowView :(UIView *)blueView  
  2. {  
  3.     NSMutableArray *constraintArray = [NSMutableArray array];  
  4.       
  5.     [constraintArray addObjectsFromArray:[NSLayoutConstraint  
  6.                                           constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|" options:0 metrics:nil  
  7.                                           views:NSDictionaryOfVariableBindings(greenView, yellowView)]];  
  8.     [constraintArray addObjectsFromArray:[NSLayoutConstraint  
  9.                                           constraintsWithVisualFormat:@"V:|-20-[greenView]-20-[blueView(==greenView)]-20-|" options:0 metrics:nil  
  10.                                           views:NSDictionaryOfVariableBindings(greenView, blueView)]];  
  11.       
  12.     [constraintArray addObjectsFromArray:[NSLayoutConstraint  
  13.                                           constraintsWithVisualFormat:@"V:|-20-[yellowView]-20-[blueView(==yellowView)]-20-|" options:0 metrics:nil  
  14.                                           views:NSDictionaryOfVariableBindings(yellowView, blueView)]];  
  15.       
  16.     [constraintArray addObjectsFromArray:[NSLayoutConstraint  
  17.                                           constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|" options:0 metrics:nil  
  18.                                           views:NSDictionaryOfVariableBindings(blueView)]];  
  19.       
  20.     return constraintArray;  
  21. }</span>  

而后横屏的约束:

 

 

[objc]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
 
  1. <span style="font-size:12px;">- (NSMutableArray *) landscapeConstraints:(UIView *)greenView :(UIView *)yellowView :(UIView *)blueView  
  2. {  
  3.     NSMutableArray *constraintArray = [NSMutableArray array];  
  4.       
  5.     [constraintArray addObjectsFromArray:[NSLayoutConstraint  
  6.                                           constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|" options:0 metrics:nil  
  7.                                           views:NSDictionaryOfVariableBindings(greenView, yellowView)]];  
  8.       
  9.     [constraintArray addObjectsFromArray:[NSLayoutConstraint  
  10.                                           constraintsWithVisualFormat:@"V:|-20-[blueView]-20-[greenView(==blueView)]-20-|" options:0 metrics:nil  
  11.                                           views:NSDictionaryOfVariableBindings(greenView, blueView)]];  
  12.       
  13.     [constraintArray addObjectsFromArray:[NSLayoutConstraint  
  14.                                           constraintsWithVisualFormat:@"V:|-20-[blueView]-20-[yellowView(==blueView)]-20-|" options:0 metrics:nil  
  15.                                           views:NSDictionaryOfVariableBindings(yellowView, blueView)]];  
  16.       
  17.     [constraintArray addObjectsFromArray:[NSLayoutConstraint  
  18.                                           constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|" options:0 metrics:nil  
  19.                                           views:NSDictionaryOfVariableBindings(blueView)]];  
  20.       
  21.     return constraintArray;  
  22. }</span>  

最后还要处理屏幕旋转:

 

 

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

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

 

 

二、view动画在autolayout实现

当布局发生改变时,至关于对子view进行从新布局,而子view从新布局调用 layoutIfNeeded,因此动画能够这样实现:

 

[objc]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
 
  1. <span style="font-size:12px;">- (void)animateConstraints  
  2. {  
  3.     [UIView animateWithDuration:0.5 animations:^{  
  4.         [self.view layoutIfNeeded];  
  5.     }];  
  6. }</span>  

Github上已经有 Demo了!

 

 

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

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

至于兼容性,只从iOS6就已经提出了autolayout的概念,如今iOS5系统不是不少了,甚至iOS6系统都已经升级为iOS7,将来一段时间大部分用户应该是使用iOS7和iOS8系统,因此兼容性问题不会太大,但size class是iOS8才有的概念,因此还有有必定的适配工做量。

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

 

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

例如:

 

[objc]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
 
  1. <span style="font-size:12px;">[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[newView]-20-|"options:0 metrics:nil views:NSDictionaryOfVariableBindings(newView, self.view)]</span>  

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

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

本篇内容全部Demo

欢迎指出错误,不胜感激。
相关文章
相关标签/搜索