一、Masonry
1.1 Masonry是快速手写Autolayout的布局框架,项目地址是https://github.com/SnapKit/Masonry 使用Masonry可以极大的提高手写布局的效率。
1.2 通过Masonry可以使用如下简单易懂的方式手写约束
[self.iconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(10);
make.top.equalTo(10);
make.width.height.equalTo(50);
}];
在https://github.com/SnapKit/Masonry/blob/master/README.md 中有详细的使用介绍可以参考。
二、UITableView+FDTemplateLayoutCell
2.1 UITableView+FDTemplateLayoutCell是自动进行UITableViewCell高度计算的,项目地址:https://github.com/forkingdog/UITableView-FDTemplateLayoutCell, 原理介绍的中文地址为http://blog.sunnyxx.com/2015/05/17/cell-height-calculation/
2.2 计算Cell高度非常简单仅需要heightForRowAtIndexPath中的一行代码。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [tableView fd_heightForCellWithIdentifier:kYLLayoutTableViewCell cacheByIndexPath:indexPath configuration:^(YLLayoutTableViewCell *cell) {
[cell setFeed:[self.viewModel.feedArray objectAtIndex:indexPath.row]];
}];
}
三、搭配使用
通过两者结合,在UITableView中使用UITableView+FDTemplateLayoutCell 计算Cell高度,使用Masonry进行autoLayout布局,能够避免高度计算的复杂,Demo地址https://github.com/yolii/Masonry-FDTemplateLayoutCell
masonry.png四、可能会踩的坑
同时在使用过程中也有一些问题需要注意,避免踩坑。这些问题中有些是高度计算的问题,有些则是autolayout的要求。
-
指定最下面view的bottom约束,这样才能够确切的计算出Cell的高度。
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.equalTo(self.iconView.leading); make.top.equalTo(self.iconView.bottom).with.offset(10); make.trailing.equalTo(-10); make.bottom.equalTo(-10); //重要 }];
-
Cell的subView要添加到contentView上,否则无法计算出准确的高度。
添加subView时需要是:
[self.contentView addSubview:_contentLabel];
而不是:
[self.view addSubview:_contentLabel]; -
iOS7设备上Cell默认高度44的约束冲突
<NSLayoutConstraint UITableViewCellContentView.height == 44>
需要在Cell初始化的时候设置contentView的autoresizingMask值
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
if (self)
{
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[self loadViews];
[self constrainViews];
}
return self;
} -
Cell需要使用tableView的registerNib或者registerClass的方法进行注册,否则会报异常。
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cell must be registered to table view for identifier - YLLayoutTableViewCell
[self.tableView registerClass:[YLLayoutTableViewCell class] forCellReuseIdentifier:kYLLayoutTableViewCell];
或
[self.tableView registerNib:[UINib nibWithNibName:@"kYLLayoutTableViewCell" bundle:nil]
-
长文本性能问题
如果label需要展示长文本,则label的宽度要固定,而不能使用lessThanOrEqualTo之类不确定约束,否则会有严重的滚动时卡顿。 -
iOS7上指定View宽度为屏幕宽度而未设置leading时,View会中心居左展示,则仅能够显示View的一半
-
Cell重用过程中的约束冲突问题
Cell重用时,高度未更新,而数据发生改变后,在高度不足的情况下,会抛高度相关的约束冲突异常。对于这种情况需要在prepareForReuse中uninstall造成冲突的约束,在设置View的时候再install.
网友评论
```swift
titleLabel.snp.makeConstraints { (make) in
// make.top.equalTo(self.snp.top).offset(20) // 这样写就计算不出来
make.leading.equalTo(11)
make.trailing.equalTo(-11)
make.topMargin.equalTo(20) // 使用 topMargin 或 make.top.equalTo(20) 就可以
}
```
https://github.com/zhenglibao/FlexLib