Auto Layout + Manual Layout 混用

约束代码混用的问题

无数人趟过此坑,大部分人在坑中一蹶不振,小部分人爬起来也是跌跌撞撞。

有很多人都说auto layout和manual layout的坐标设置是不能混用的,会导致出现布局问题。首先声明一点,autolayout和manuallayout是可以混用的。用的时机很重要,auto layout和manual layout有各自的生命周期和作用域,区分他们两个的作用时间很关键,头脑中一定要清楚你所添加的每条约束,在什么时间场合,会造成什么后果。否则,布局就会和预想的不同,各种奇怪的布局问题也就接踵而至。

1)视图的生命周期顺序

我们在controller视图上面用auto layout添加了一个subview,并在各个系统调用声明周期方法中做了打印处理,结果如下:

其中前面带有“-”符号的表示的是subview视图的打印。

autolayout的作用范围是从上往下第三个方法-updateConstraints一直到viewDidLayoutSubviews,这期间,系统是通过view上的约束来计算view上的布局。而我们一般习惯将布局写在viewDidLoad里面,这就是我们为什么总是无法用manual layout的方法去修改我们的布局。

要想修改布局,必须要在autolayout结束之后才会起作用,否则会被系统将我们的布局按照autolayout重新刷新,从上面我们可以看到,我们可以在子视图的-layoutSubviews和-drawRect方法里面修改子视图的布局,但是一般视图为了重用不会在自己的类里面将frame写死,这样我们只有通过controller的viewDidAppear方法修改视图的frame。但是这样也有问题,在viewDidAppear里面修改布局,我们可以看到一个明显的延迟,系统调用次序使然,我们无法去改变。除此之外,如果我们更新了视图的autolayout,会导致视图重新调用updateViewConstraints方法,viewDidAppear在进入页面的时候却只调用一次,结果就是subview又恢复了原来的样子。

所以我的建议就是不要同时manual layout+auto layout去控制同一个视图。始终记得如果用了auto layout去控制了一个视图,那么就要坚持用下去。

2)何为混用

我觉得混用的说法不是对于某一个视图说的,是说我们整个布局当中交叉使用了manual layout + auto layout,比如我们可以用auto layout布局viewA,然后用manual layout 布局B,然后将A与B用两者其一的方式,添加到共同的父viewC上,这就是我所认为的混用。

那么它的意义是什么呢?不同view的复杂度决定了我们采取哪种方式来对其布局,我们在开发中有可能会遇到某些流式的布局,我们用autolayout可以行云流水,但是对于某个视图当中极其复杂的小控件的布局,auto layout显然要写不少的一大段,当两者组合时也就是混用的意义所在。

3)如何混用

混用的风险其实一点不比它带来的好处小,首先解释一个名字

NSAutoresizingMaskLayoutConstraint

这个类型和NSLayoutConstraint 功能类似,它是个私有类,我们无法获取到,因为苹果ios6之后推出了auto layout技术,但是还想兼容原来的autoresizing,所以它将autoresizing转化为了约束,转化后的约束类型就是NSAutoresizingMaskLayoutConstraint,这就有可能导致系统为我们添加了许多我们无法预料的约束。

我们有时候会发现我们的约束没有写全,但是布局却很好,千万不要太得意,这只是系统帮你完成你该做的,这种情况固然对我们有好处。但是在manual layout +  auto layout布局中就会发生大问题,系统不懂我们是在故意不写它的约束(因为我们打算手动布局这一块的视图),它就默默帮我们加上了谁都不知道的约束,并为自己的机智暗自欣喜。我们要明确告诉它我不需要你的帮助才行。

UIView里translatesAutoresizingMaskIntoConstraints属性就是用来控制是否允许系统做这样的转化,默认是YES。所以我们要把它设置为NO,然后将你漏掉的约束统统加上。

怎样算作完备的约束呢,我的建议是把视图层次分清楚,每个层次系统内部使用统一的布局方案,并保证系统内的的约束完整。

这是一个视图的层级拓扑结构(原谅我又盗图了,凑合看吧),如果我打算在做黄箭头位置的视图布局时采用auto layout,其他采用manual layout那么我只需保证它及它下面的两个子视图之间的约束完整就可以了,他们三个可以当做一个小的系统,系统内的约束只与他们自己相关,像下面两个红线连接的视图间的约束就是不允许添加的。

图:错误的约束关系

4)最后

以上就是我想说的,混用这种手段还是希望大家谨慎使用为好,最后总结一下混用的关键点

1.首先要确保在你打算使用手写auto layout为view布局前,将其translatesAutoresizingMaskIntoConstraints属性设为NO

2.不要用对同一个视图同时使用manual layout +  auto layout

3.确保你的约束在其系统内完整无缺失。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )