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