iOS8.0新特性 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)最基本的约束实现方式
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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)特殊格式化语言的约束实现方式
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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:
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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>  

接下来适配竖屏的约束:
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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>  

然后横屏的约束:
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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>  

最后还要处理屏幕旋转:
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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,所以动画可以这样实现:
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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详解,可想达到详解还需要更多的时间去实践和总结,还有一些细节没有体现出来:
例如:
[objc] view plaincopy在CODE上查看代码片派生到我的代码片 
<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-|" 这种可视化布局字符串的含义等等,有空再补充了!
本篇内容所有Demo
欢迎指出错误,不胜感激。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值