Masonry框架初次使用遇到的坑 frame为0
实现自适应布局的一个非常方便的方法就是使用Masonry框架,然而使用Masonry布局的时候,并不能立刻反应到frame
的改变上,比如:
UIView *parent = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
UIImageView *child = [UIView alloc] init];
[parent addSubview:child];
[child mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(20,20));
make.top.left.mas_equalTo(50);
}];
NSLog(@"%@",redView);
打印结果:
** <UIImageView: 0x7fb222605550; frame = (0 0; 0 0); layer = <CALayer: 0x7fb22260b3a0>>**
可以发现,虽然使用Masonry进行布局和约束,但是子视图child
的frame
仍然为(0, 0, 0 ,0).
而这时候如果有需求要设置child的形状为圆形,就得知道它的frame,像下面这样写肯定不会设置成功的:
[child mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(20,20));
make.top.left.mas_equalTo(50);
}];
child.layer.cornerRadius = child.bounds.size.width/2;
child.layer.masksToBounds = YES; //设置头像为圆形
因为这时候的frame还是0。我想会不会是因为block中的处理是放在另一个线程中异步进行的,block还没执行完就已经走到了下面使用frame的代码,(一阵狂喜,好聪明。。。),所以马上把代码改写:
[child mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(20,20));
make.top.left.mas_equalTo(50);
child.layer.cornerRadius = child.bounds.size.width/2;
child.layer.masksToBounds = YES; //设置头像为圆形
}];
然而并没有什么卵用。。。
没办法只能问谷歌了,然后找到了Masonry约束下获取frame
的方法:
使用masonry的实质还是调用了ios7以后的autolayout,如果要更新frame
,需要调用layoutIfNeeded
函数进行布局,然后所约束的控件才会按照约束条件,生成当前布局相应的frame
和bounds
。这样就可以利用这两个属性来进行图片圆角剪裁。而调用layoutIfNeeded
的目的是让系统调用layoutSubviews
方法,我们也可以直接在这个方法里获取frame,因为这时候开始layout subviews,Masonry已经计算出了真实的frame。
下面附上关于autolayout更新几个方法的区别:
setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。
layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点,动画可以在更新布局后直接使用这个方法让动画生效。
layoutSubviews:系统重写布局
setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始
updateConstraintsIfNeeded:告知立刻更新约束
updateConstraints:系统更新约束