UIView如何优雅的自适应布局(Masonry)
Posted Garenge
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UIView如何优雅的自适应布局(Masonry)相关的知识,希望对你有一定的参考价值。
怎么安装Masonry和怎么makeConstraints不多说, 我们假设你会...
cell的高度自适应
开发中常常需要UITableViewCell高度自适应, 最最常见的, 就是UILabel的多行文字显示, 我们都是让内部view自适应来撑起父视图. 一般的view自适应我们也是这么做的
子view撑起父view
比如, 我们在界面中间需要放一个contentView, 居中, view的内部呢, 我们假设有一个子view-innerView, 上下左右距离父视图均为20, 我们一般配合Masonry, 可以这么写:
UIView *contentView = [[UIView alloc] init];
contentView.backgroundColor = [UIColor blueColor];
[self.view addSubview:contentView];
UIView *innerView = [[UIView alloc] init];
innerView.backgroundColor = [UIColor redColor];
[contentView addSubview:innerView];
[innerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsMake(20, 20, 20, 20));
make.size.mas_equalTo(CGSizeMake(100, 100));
}];
[contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.centerY.mas_equalTo(0);
}];
通常写法
这里有一个注意点是我们把这个contentView加到self.view上去了, 最终我们其实并不需要知道他的frame是多少.
需要结果的自适应
开发中还有一种是我们需要知道frame的情况, 给tableView设置tableHeaderView, 或者其他什么框架, 需要我们提供一个有已知frame的view, 这时候怎么办呢, 我们试试, 把contentView不设置父视图, 打印一下他的frame
UIView *contentView = [[UIView alloc] init];
contentView.backgroundColor = [UIColor blueColor];
UIView *innerView = [[UIView alloc] init];
innerView.backgroundColor = [UIColor redColor];
[contentView addSubview:innerView];
[innerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsMake(20, 20, 20, 20));
make.size.mas_equalTo(CGSizeMake(100, 100));
}];
[contentView layoutIfNeeded];
NSLog(@"%@", NSStringFromCGRect(innerView.frame)); // {{20, 20}, {0, 0}}
NSLog(@"%@", NSStringFromCGRect(contentView.frame)); // {{0, 0}, {0, 0}}
都是0, 这时候我们设置view肯定不成功啊, 都是0, 咋整呢?
我们创建view, 内部那么多子view, 让我通过高低来计算出frame, 不是不可以, 很麻烦, 也很chǔn, 那我们能不能, 还是让他自适应, 我约束子视图, 最后在不添加到父视图的情况下, 直接获取到contentView的size呢?
优雅的自适应
很简单, 直接在[contentView layoutIfNeeded];前面加一句话
...
[contentView mas_makeConstraints:^(MASConstraintMaker *make) {
// 可以什么都不写, 或者你写上其他的约束
}];
[contentView layoutIfNeeded];
NSLog(@"%@", NSStringFromCGRect(innerView.frame)); // {{20, 20}, {100, 100}}
NSLog(@"%@", NSStringFromCGRect(contentView.frame)); // {{-70, -70}, {140, 140}}
contentView并不需要添加到父视图, 由于其内部视图已经做好了约束, 确实把它撑起来了.
最后我们得到innerView 是100* 100, contentView是140 * 140, 因为frame.origin我们没有设置, 显示的是-70, 这个不重要, 当他被添加到其他视图上时, origin会自动更改的.
到这一步, 我们得到一个view, 我只要把内部的view约束好, 就能拿到他的frame, 这样我设置header或者其他需要的地方的时候, 我可以直接给出正确的size, 就不需要自己去计算, 是不是很优雅.
实战
headerView
这是我们常见的用户信息, 我现在要求你只传给我一个有已知size的headerView
那我们的方法就如下
- (UIView *)getHeaderView {
UIView *headerView = [[UIView alloc] init];
UIView *iconView = [[UIView alloc] init];
[headerView addSubview:iconView];
[iconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(20);
make.height.mas_equalTo(40);
make.width.mas_equalTo(40);
make.left.mas_equalTo(20);
}];
UIView *nameView = [[UIView alloc] init];
[headerView addSubview:nameView];
// 写法1
// [nameView mas_makeConstraints:^(MASConstraintMaker *make) {
// make.top.equalTo(iconView.mas_bottom).with.offset(20);
// make.left.mas_equalTo(20);
// make.right.mas_equalTo(-20);
// make.height.mas_equalTo(40);
// make.bottom.mas_equalTo(-40);
// }];
//
// [headerView mas_makeConstraints:^(MASConstraintMaker *make) {
// make.width.mas_equalTo(320);
// }];
// 写法2
[nameView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(iconView.mas_bottom).with.offset(20);
make.left.mas_equalTo(20);
make.right.mas_equalTo(-20);
make.width.mas_equalTo(280);
make.height.mas_equalTo(40);
make.bottom.mas_equalTo(-40);
}];
[headerView mas_makeConstraints:^(MASConstraintMaker *make) {
}];
[headerView layoutIfNeeded];
NSLog(@"%@", NSStringFromCGRect(headerView.frame)); // {{-160, -80}, {320, 160}}
NSLog(@"%@", NSStringFromCGRect(iconView.frame)); // {{20, 20}, {40, 40}}
NSLog(@"%@", NSStringFromCGRect(nameView.frame)); // {{20, 80}, {280, 40}}
return headerView;
}
其中写法1就是headerView限制了宽度320, 里面的nameView左右距离20, 那么nameView就是280
写法2就是nameView限制了宽度280, 左右各20, 那headerView宽就是320
至此, 我们在还没有加到父视图上, 还没有对headerView有任何人为计算的情况下, 获得了一个已知size的headerView, 拿去干别的事岂不是很方便?
以上是关于UIView如何优雅的自适应布局(Masonry)的主要内容,如果未能解决你的问题,请参考以下文章