iOS表视图高度自适应可以节省很多麻烦,尤其是涉及到复杂的业务逻辑时,今天尝试了使用Masonry和FDTemplatelayoutCell来布局表视图单元格,从而达到单元格高度自适应的效果,这里就总结了这其中使用的要点和注意问题。
首先,为了实现表视图的单元格高度自适应,我们需要用到Masony和FDTemplatelayoutCell这两个第三方的类库。同时这里使用一个简化的订单界面来说明使用,效果图如下:
一、Masonry和FDTemplatelayoutCell实现自适应
Masnory帮助我们在单元格中设置约束,实现视图的自动布局,这里不再赘述(网上资料很多)。我们需要做的就是使用Masonry对视图单元格中的位于最底部的视图设置bottom约束,使其能够确定距离单元格最低端的距离。一个代码示例如下:
//显示订单价格的Label的约束设置
[self.orderPriceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.SponsorNameLabel.mas_bottom);
make.left.equalTo(self.headerImgView.mas_right).offset(leftForHeaderImg);
make.right.equalTo(self.contentView).offset(-10);
make.height.mas_equalTo(25);
make.bottom.mas_offset(-10);//关键代码,设置距离底部10
}];
FDTemplatelayoutCell 是实现单元格高度自适应的关键代码,是UITableView的类目文件。使用的时候关键步骤包括:
1、注册表视图的单元格
这里分为NIb文件和普通类文件的单元格注册,我使用的是xib文件创建的单元格,代码如下:
- (UITableView *)tableView{
if (_tableView == nil) {
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, kDeviceWidth, kDeviceHeight- 64) style:UITableViewStylePlain
];
//注册单元格
[_tableView registerNib:[UINib nibWithNibName:@"OrderTableViewCell" bundle:nil] forCellReuseIdentifier:self.reuseCellID];
_tableView.dataSource = self;
_tableView.delegate = self;
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
return _tableView;
}
2、返回单元格高度
返回单元格高度我们就不必计算了,使用如下的方法来返回
//单元格高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//调用了FDTemplateLayoutCell的方法
return [tableView fd_heightForCellWithIdentifier:self.reuseCellID configuration:^(OrderTableViewCell *cell) {
//回调中要设置数据
cell.dataDic = self.dataSource[indexPath.row];
}];
}
二、遇到的问题:
1.Masonry设置的约束无效
我们要确定设置单元格子视图约束是相对于contentView的,如下的约束就是错误的。因为在布局的时候是相对于self的,这样可能会使约束错乱,自适应高度无效。
[self.separateLineView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.equalTo(self);
make.height.mas_equalTo(10);
}];
2.结合xib类型单元格使用时的错误
因为我使用了xib文件来加载视图的,所以开始的时候写了如下方法获取单元格
//获取单元格
+ (OrderTableViewCell *)getOrderTableViewCell{
NSArray *array = [[NSBundle mainBundle]loadNibNamed:@"OrderTableViewCell" owner:nil options:nil];
OrderTableViewCell *view = array[0];
//设置约束
[view setupConstraints];
return view;
}
//返回单元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *identifier = self.reuseCellID ;
//单元格注册过,一直可以获取到到单元格
OrderTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.reuseCellID];
if (cell == nil) {
//这里代码不会执行,方法中设置约束的代码也不会执行
cell = [OrderTableViewCell getOrderTableViewCell];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.dataDic = self.dataSource[indexPath.row];
return cell;
}
因为单元格是注册的,所以在返回单元格方法里判断单元格是否存在是没有意义的,getOrderTableViewCell不会调用,在这个方法里设置的布局约束也是无效的。
修改的方法是如下;
- (void)awakeFromNib {
[super awakeFromNib];
//awakeFromNib方法中添加约束
[self setupConstraints];
}
//返回单元格,不再使用getOrderTableViewCell方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
OrderTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.reuseCellID];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.dataDic = self.dataSource[indexPath.row];
return cell;
}
四、资料链接
demo示例:
https://github.com/DreamcoffeeZS/Demo_FDTemplateLayoutCell
Masonry下载:
https://github.com/SnapKit/Masonry
Masonry的使用:
https://github.com/SnapKit/Masonry/blob/master/README.md
FDTemplateLayoutCell下载:
https://github.com/forkingdog/UITableView-FDTemplateLayoutCell