美文网首页实用iOS 日常学习Ios@IONIC
使用Autolayout实现cell自适应高度

使用Autolayout实现cell自适应高度

作者: 芝麻酱的简书 | 来源:发表于2016-04-28 18:04 被阅读584次

    -------推荐使用最下方的【改进】方法-------
    (前排补上一个简单的小Demo:https://github.com/3KK3/AutoFitDemo/tree/master
    时间仓促,有些许不足,敬请见谅。)

    方法一:

    1. 对cell的subview增加针对于contentView的约束(注意设置文字的最大宽度);

    2. 设置tableview预估高度estimateHeight

    3. 在cell拿到数据的地方cellForRowAtIndexPath,进行强制刷新布局:先根据数据和cell控件要求计算实际高度,并存入dataModel模型(做缓存),然后调用方法[self layoutIfNeeded](第一次显示内容的时候 无需调用setNeedsLayout),这样heightForIndexPath会紧随其后获取cell的真实高度,此时存入模型的cell的高度就起了作用了

    PS:

    预估高度机制 启用后 改变cell的加载顺序

    • 原来的顺序 : 先调用heightForRowAtIndexPath获取真实高度,拿到高度之后再调用cellForRowAtIndexPath渲染cell内容

    • 启用预估高度之后:先调用estimatedHeightForRowAtIndexPath返回代理估计高度,然后再根据预估高度调用cellForRowAtIndexPath渲染cell内容,同时计算真实高度,最后再调用heightForRowAtIndexPath拿到计算的真实高度 显示


    方法二:

    1. 对cell的subview增加针对于contentView的约束(注意设置文字的最大宽度)

    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
           //只创建一个cell用作测量高度
    
      static MyCell *cell = nil;
    
      if (!cell) cell = [self.tableView  dequeueReusableCellWithIdentifier:@"MyCell"];
    
         //这里把数据设置给Cell
    
      cell.titleLabel.text = [_dataSource objectAtIndex:indexPath.row];
    
      [cell layoutIfNeeded];
    
      [cell updateConstraintsIfNeeded];
    
    
    
    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    
    return height;
    
    }
    
    

    方法三:

    1.在cell中设置多行label的约束:

    // 计算UILabel的preferredMaxLayoutWidth值,多行时必须设置这个值,否则系统无法决定Label的宽度
    CGFloat preferredMaxWidth = [UIScreen mainScreen].bounds.size.width - (16 + 4) * 2 - 44 - 4;
    // Content - 多行
    _contentLabel = [UILabel new];
    _contentLabel.numberOfLines = 0;
    _contentLabel.preferredMaxLayoutWidth = preferredMaxWidth; // 多行时必须设置
    [self.contentView addSubview:_contentLabel];
    [_contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {   
    
        make.top.equalTo(_titleLabel.mas_bottom).with.offset(4);    
        make.left.equalTo(_avatarImageView.mas_right).with.offset(4);   
        make.right.equalTo(self.contentView).with.offset(-4); 
        make.bottom.equalTo(self.contentView).with.offset(-4);}
    ];
      // 设置高度的Content Hugging
      [_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    
    

    2.UITableView
    再看看UITableView。
    用systemLayoutSizeFittingSize:获取Cell的高度
    在设定好Cell的约束以后,就可以用systemLayoutSizeFittingSize:方法获取Cell的实际高度,它的参数可以设定为两个系统常量,如下:
    UILayoutFittingCompressedSize: 返回合适的最小大小。
    UILayoutFittingExpandedSize: 返回合适的最大大小。

    为了在“- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath ”方法中计算Cell的高度,我们需要一个专门用于计算高度的Cell实例,可以说算是Cell的“模板”。一般来说,这个实例可以设置成函数的static变量,并只在第一次使用时初始化一次。

    model简单缓存高度
    为了避免每次滑动时计算高度,可以将Cell的高度缓存下来。如,保存在每一行对应的数据Model(Entity)中,例如:

    @interface Entity : NSObject
    // Data
    @property (copy, nonatomic) NSString *title;
    // ...// Cache height
    @property (assign, nonatomic) CGFloat cellHeight;
    @end
    

    tableView代理方法中代码:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
     static Case4Cell *templateCell; static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ templateCell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([Case4Cell class])]; });
     // 获取对应的数据
     Case4DataEntity *dataEntity = _data[(NSUInteger) indexPath.row];
     // 填充数据 
    [templateCell setupData:dataEntity];
     // 判断高度是否已经计算过
     if (dataEntity.cellHeight <= 0) { 
      // 根据当前数据,计算Cell的高度,
      // ------ 注意+1 ------
      dataEntity.cellHeight = [templateCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1; 
    }
     return dataEntity.cellHeight;
    }
    

    改进:

    iOS 8的新特性
    iOS 8大大简化了Cell的高度计算,只要:
    1.设置好Cell中控件的约束;

    1. 然后 UITabelView初始化时候:
    // UITabelView初始化时候
    tableView.rowHeight = UITableViewAutomaticDimension;
    tableView.estimatedRowHeight = 80;
    

    3.在UITableview 代理方法:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
      // 只用返回这个! 
      return UITableViewAutomaticDimension;
    }
    

    相关文章

      网友评论

      • dd2cd3e8a0e7:重点在最后啊。解决了这个场景困扰:tableView有的cell需要自适应,有的需要直接定义高度。:pray:

      本文标题:使用Autolayout实现cell自适应高度

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