AutoLayout自适应Cell高度

作者: 逆风g | 来源:发表于2017-06-21 13:43 被阅读33次

iOS中tableview是一个经常用的控件,尤其它的cell高度计算令人头疼。考虑到tableview的性能优化,我们一般都会在model封装时提前计算好cell的高度,代理返回cell高度时,拿到model,直接给它已计算好的高度。iOS8.0之后,可以使用AutoLayout结合tableview的属性让cell自己计算出高度。

使用步骤

  • cell中使用Autolayout布局,例如这样:
    Cell的AutoLayout样式.png
    cell高度=约束1的值+label1的高度+约束2的值+label2的高度+约束3的值
    文字内容动态变化,那么label高度会动态变化,最终cell高度也会动态变化。
  • 显设置tableview的属性:
//给tableview设置一个默认高度
self.tableView.estimatedRowHeight = 45;
//告诉tableview,cell是自适应的
self.tableView.rowHeight = UITableViewAutomaticDimension;

常遇问题

  • label的lines设置为1,label不能换行,高度始终是一行的高度,应该酌情设置,一般设置0即可,不限行高。


    image.png
  • contentview的高度没有被子视图约束填充满。


    image.png
  • label的宽度因为缺少约束而没法确定。


    image.png
  • 约束报错,列如:


    cell的约束错误.png

    因为bottom的约束值与实际的值不符,可以改变约束值,或者改变cell的高度

  • 使用storyboard绘制的cell,Controller中注册了cell子类,导致绘制的cell显示不出来。


    cell样式.png

不需这样

//    [self.tableView registerClass:NSClassFromString(@"MyTableViewCell1") forCellReuseIdentifier:cellId1];
//    [self.tableView registerClass:NSClassFromString(@"MyTableViewCell2") forCellReuseIdentifier:cellId2];

直接这样即可

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row<self.data1.count) {
        MyTableViewCell1 *cell = [tableView dequeueReusableCellWithIdentifier:cellId1 forIndexPath:indexPath];
        cell.model=self.data1[indexPath.row];
        return cell;
    }else
    {
        MyTableViewCell2 *cell = [tableView dequeueReusableCellWithIdentifier:cellId2 forIndexPath:indexPath];
        cell.model=self.data2[indexPath.row-self.data1.count];
        return cell;
    }
}
  • cell的高度显示不正确,需要刷新下tableview,才会显示正确。那是因为cell中label的赋值是在layoutSubviews完成的。
-(void)layoutSubviews
{
    [super layoutSubviews];
    self.lbl.text=self.model.contentStr;
}

要么:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row<self.data1.count) {
        MyTableViewCell1 *cell = [tableView dequeueReusableCellWithIdentifier:cellId1 forIndexPath:indexPath];
        MyModel1 *model=self.data1[indexPath.row];
        cell.lbl1.text=model.str1;
        cell.lbl2.text=model.str2;
//        cell.model=self.data1[indexPath.row];
        return cell;
    }else
    {
        MyTableViewCell2 *cell = [tableView dequeueReusableCellWithIdentifier:cellId2 forIndexPath:indexPath];
        MyModel2 *model=self.data2[indexPath.row];
        cell.lbl.text=model.contentStr;
//        cell.model=self.data2[indexPath.row-self.data1.count];
        return cell;
    }
}

很多情况下我们还是希望赋值操作是在cell类中完成时,也可以这样:

- (void)showData
{
    self.lbl1.text=self.model.str1;
    self.lbl2.text=self.model.str2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row<self.data1.count) {
        MyTableViewCell1 *cell = [tableView dequeueReusableCellWithIdentifier:cellId1 forIndexPath:indexPath];
        cell.model=self.data1[indexPath.row];
        [cell showData];
        return cell;
    }else
    {
        MyTableViewCell2 *cell = [tableView dequeueReusableCellWithIdentifier:cellId2 forIndexPath:indexPath];
        cell.model=self.data2[indexPath.row-self.data1.count];
        [cell showData];
        return cell;
    }
}

进阶

假若label在contentview的多级子视图中也是可以实现cell高度自适应的。


image.png

原理也是同样的

demo效果

image.png image.png

demo在这里

相关文章

网友评论

    本文标题:AutoLayout自适应Cell高度

    本文链接:https://www.haomeiwen.com/subject/qsdaqxtx.html