containerView 是storyboard中的重要组件,通过添加containerView可以轻易的对页面进行分离。基本使用和普通组件一样。但是想动态变高(变宽同理)就会遇到问题,找到的相关资料比较少,最终还是解决了问题。我们来模拟项目中实际使用的情况。
第一步: 添加一个containerView
设置居中,左右边距0,此时会报错没有高度。由于我们需要根据真实的子组件来定高,所以这里不能给定一个确定的值。

此时,有两个方法解决。
方法一:设定固定高度,设置低优先级。
因为真实的高度优先级都是1000,所以这里只要优先级低(一般设置250或以下),根据真实高度算出的高度就有优先使用,这里也不会有报错。

方法二:设置intrinsic size
,默认这个是使用真实宽高,这里我们调整为placeholder即可。

从红框中的说明也可以看出,这个设置只是在IB中起到设定作用,在真实渲染的时候不会生效。所以如果我们内部不是撑高的,这里在实际运行的时候一样会报没有高度的约束错误。
intrinsic size
的全称是 intrinsicContentSize
是view的一个属性,作用就是view 根据自己的内容算出来的一个宽高。具体的还会涉及到一些autolayout的高级用法,这里不展开了。后面新开文章填坑。
第二步: 子控制器中添加元素,撑起视图。
子控制器大小和containerView的大小一样,不方便操作。我们此时通过设置simulated size
去调整大小。

调整到合适大小后,加入其他控件,和其他自动计算的撑高方式一样,在最下方的一个组件要设置居下为 0。比如我们添加一个左边距,上边距都是0,宽高都是100的橘色View,这时我们再设置居下为0则会出现报错(和高度约束冲突)。
此时的处理也是多种方式,第一种是设置居下的距离优先级(一般设置为750-999,1000为默认优先级会报错,同时如果第一步中是设置的高度优先级,那这里要比第一步中的高),或者是设置为大于等于0也可以起到同样的效果。第二种是调整大小,让其刚好居下的距离是0,这样也满足条件不报错。
第三步:设置使用autolayout自动计算
在子控制器中,需要设置self.view.translatesAutoresizingMaskIntoConstraints = NO;
表示不使用Autoresizing(全称是view的属性autoresizingMask)进行Frame的计算,即用Autolayout的方式计算(笔者认为这更类似于优先级选择的一个概念,即如果是YES,优先使用autoresizing进行计算,即使设置了约束也是无效的,NO,即优先使用约束,设置了autoresizingMask属性也是无效的)。
当把组件刚放入父控件时,默认是autoresizing的,在检查器中可以看到下图所示。

组件加上任意约束后,则变成如下图所示。

关于该属性头文件中表述的很清楚:
/* By default, the autoresizing mask on a view gives rise to constraints that fully determine
the view's position. This allows the auto layout system to track the frames of views whose
layout is controlled manually (through -setFrame:, for example).
When you elect to position the view using auto layout by adding your own constraints,
you must set this property to NO. IB will do this for you.
*/
@property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints API_AVAILABLE(ios(6.0)); // Default YES
IB will do this for you.
这就是我们添加约束后检查器界面发生变化的原因。然而对于viewcontroller的view,我们无法对其添加约束,即在IB中,这个属性就是默认的YES,IB中无法更改。
containerView的本质就是把这个子控制器的View添加到当前view上,这样要是想使用autolayout布局就只能代码设置该属性为NO。

至此,一个动态计算高度的containerView 就完成了。关键就是第三步属性的设置。
疑问:
有的同学疑问,设置了containerView的约束,后面子控制器的view加在这里为什么还要设置translatesAutoresizingMaskIntoConstraints
?
参考下图的设置,containerView设置红色,子控制器View设置橘色,里面方一个蓝色方块。

查看运行时图层的结构:

可以看出设置containerView的约束只能保证containerView的该属性是NO。橘色的View是作为控制器的View加在这个containerView中,而控制器的view该属性是默认的YES。同时,我们也发现,如果要操作这个View,比如子控制器view的显示/隐藏 ,也必须通过操作红色的view进行。
网友评论