Masonry布局控件frame为0的问题

凶猛老鹰IP属地: 北京
1字数 767阅读 2,657

Masonry 是对 autolayout 的封装,优雅的链式语法和简洁易用的接口让我们在做UI开发时节省了不少时间。然而在初次使用它时,由于还对 autolayout 理解不够深,就遇到了一些问题,比如使用 Masonry 对控件添加约束后,并不会立即生效,frame 仍然是 0。如果此时我们需要这个 frame,应该怎么做呢?

使用 Masonry 添加约束后,如果有要设置 child 的形状为圆形,就得知道它的 frame,像下面这样写肯定不会设置成功的:

因为这时候的 frame 还是 0。曾天真的想,会不会是因为 block 中的处理是在异步线程进行的,不会等待 block 执行完就已经走到了下面使用frame的代码,(一阵狂喜,好聪明。。。),所以马上把代码改写:

然而并没有什么卵用。

想不通的时候,就只能请教 goole 了,然后找到了 Masonry 约束下获取 frame 的方法

masonry 本就是对 autolayout 的封装,使用 Masonry 就等于使用了苹果的 autolayout。使用 masonry 布局完之后,系统会在某个时间点调用各个 view 的 layoutSubViews 方法,从而更新各个控件的frame。遗憾的是,frame 的更新并不会在刚执行完 Masonry 布局代码时立即进行,在布局代码的下一行,你所获取到的 frame 仍然是0。

想要在布局代码结束就立即获取当前某个控件正确的 frame,需要调用layoutIfNeeded函数立即刷新布局,各个控件才会按照约束条件,生成当前布局相应的frame和bounds。而调用layoutIfNeeded的目的是让系统调用layoutSubviews方法,我们也可以直接在这个方法里获取frame,因为这时候开始layout subviews,Masonry已经计算出了真实的frame。

下面附上关于autolayout更新几个方法的区别:

setNeedsLayout:标记页面需要更新,但是什么时候才会调用

layoutSubviews 去刷新布局,就不一定了。

layoutIfNeeded:告知页面如果需要,就立刻更新布局。这里的“如果需要”什么意思呢?有什么条件吗?是的,只有满足如下某一个或几个条件,调用 layoutIfNeeded 才会立即刷新frame:

有 addSubview 操作

设置了view的 frame,当然前提是设置前后 frame 的值发生了变化

滚动一个UIScrollView

旋转 Screen

改变一个UIView大小的时候

如果不满足,就算是调用了 layoutIfNeeded 也不会立刻执行 layoutSubViews 进行 frame 更新。

如果我们想不管什么情况,都强制执行 layoutSubViews 进行 frame 更新怎么办呢?那就是同时调用下面这两个方法:

这样必然会调用 layoutSubViews 。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
51人点赞
更多精彩内容,就在简书APP
"小礼物走一走,来简书关注我"
还没有人赞赏,支持一下
总资产42共写了5.0W字获得1,756个赞共10个粉丝

推荐阅读更多精彩内容