UITableViewCell高度自适应

参考文档

比较Masonry 和 SDAutoLayout 两个自动布局其实各有优劣,在使用上SDAutoLayout更方便简单,Masonry感觉功能更全面一些,并且SDAutoLayout 和 MyLayout 都是对frame的封装。

1. Masonry + 估算高度
- (UITableView *)tableView{
    if (!_tableView) {
        _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, kWidth, kHeight ) style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;

        //直接用估算高度
        _tableView.rowHeight = UITableViewAutomaticDimension;
        _tableView.estimatedRowHeight = 80;
        
        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        [_tableView registerClass:[PUshMessageCell class] forCellReuseIdentifier:@"PUshMessageCell"];
        
    }
    return _tableView;
}

//*****cell 文件中主要方法*****//
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self setup];
    }
    return self;
}
- (void)setup{
  
  //logo图片
    _logoImageView = [[UIImageView alloc]init];
    _logoImageView.image = [UIImage imageNamed:@"faghoo-logo"];
    [self.contentView addSubview:_logoImageView];
    [_logoImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(@28);
        make.left.equalTo(@10);
        make.width.height.equalTo(@40);
    }];

 //时间
    _timeLabel = [[UILabel alloc]init];
    [self.contentView addSubview:_timeLabel];
    [_timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_logoImageView.mas_top);
        make.centerX.equalTo(self.contentView);
    }];
   
   //文字背景图片
    UIImageView *containView = [[UIImageView alloc]init];
    containView.clipsToBounds = YES;
    UIImage *image = [UIImage imageNamed:@"qipao"];
    containView.image = [image resizableImageWithCapInsets: UIEdgeInsetsMake(50, 50, 50, 50) resizingMode:UIImageResizingModeStretch ];
    [self.contentView addSubview:containView];
        
    [containView mas_updateConstraints:^(MASConstraintMaker *make) {
        
        make.top.equalTo(_timeLabel.mas_bottom).offset(10);
        make.left.equalTo(_logoImageView.mas_right).offset(7);
        make.right.lessThanOrEqualTo(self.contentView).offset(-10);
        make.bottom.offset(-10).priorityLow();

    }];

    //文字Label
    _messageLabel = [[MLLinkLabel alloc]init];
    [containView addSubview:_messageLabel];
    _messageLabel.numberOfLines = 0;
    
   
   // _messageLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 10-40 -7- 25-20;
    
    [_messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.top.equalTo(containView.mas_top).offset(10);
        make.left.equalTo(containView.mas_left).offset(25);
        make.right.equalTo(containView.mas_right).offset(-10);
        make.bottom.equalTo(containView.mas_bottom).offset(-10);

    }];
   [_messageLabel setContentHuggingPriority:1000 forAxis:UILayoutConstraintAxisVertical];
    
   //设置label中链接方法
    [_messageLabel setDidClickLinkBlock:^(MLLink *link, NSString *linkText, MLLinkLabel *label) {
        if (link.linkType==MLLinkTypeURL) {
            
            NSString *url = [NSString stringWithFormat:@"%@",link.linkValue];
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
            
        }

    }];
}
2.Masonry/XIB + UITableView+FDTemplateLayoutCell

TableView如果用估算高度的话,可能会出现卡顿,系统性能有损耗较大。所以结合正确约束自动适应高度是比较合适的。

#import <UITableView+FDTemplateLayoutCell.h>
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    //有缓存
    return [tableView fd_heightForCellWithIdentifier:@"identifer" cacheByIndexPath:indexPath configuration:^(id cell) {
        // 配置 cell 的数据源,和 "cellForRow" 干的事一致,比如:
        cell.entity = self.feedEntities[indexPath.row];
       }];
    //无缓存
    return [tableView fd_heightForCellWithIdentifier:@"reuse identifer" configuration:^(id cell) {
        // Configure this cell with data, 
        //same as what you've done in "-tableView:cellForRowAtIndexPath:"
        // Like:
        cell.entity = self.feedEntities[indexPath.row];
       }];
}



//*****cell 文件中主要方法*****//
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self setup];
    }
    return self;
}
- (void)setup{
    _godImageView = [[UIImageView alloc]init];
    [self.contentView addSubview:_godImageView];
    
   //图片
    [_godImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(@12);
        make.left.equalTo(@12);
        make.width.height.equalTo(@46);
        make.bottom.equalTo(@-10).priorityLow();
    }];
    
   //标题
    _godTitle = [[UILabel alloc]init];
    [self.contentView addSubview:_godTitle];
    [_godTitle mas_makeConstraints:^(MASConstraintMaker *make){
       
        make.top.equalTo(@16);
        make.left.equalTo(_godImageView.mas_right).offset(10);
        make.right.lessThanOrEqualTo(self.mas_rightMargin);  
    }];
    
 //内容
    _contentMLabel = [[MLLabel alloc]init];
    _contentMLabel.numberOfLines = 0;
    _contentMLabel.lineSpacing = 5;
    [self.contentView addSubview:_contentMLabel];
    _contentMLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 63;
    [_contentMLabel mas_makeConstraints:^(MASConstraintMaker *make) {
       
        make.top.equalTo(_godTitle.mas_bottom).offset(7);
        make.left.equalTo(_godTitle);
        make.right.equalTo(self.contentView).offset(-12);
       make.bottom.equalTo(self.contentView).offset(-10);
        
    }];
Notes:

FDTemplateLayoutCell有两种计算高度的模式

  1. 是AutoLayout使用的-systemLayoutSizeFittingSize:
  2. 是Frame使用的-sizeThatFits:
    可以通过fd_enforceFrameLayout = YES 开启Frame模式,
    注意,开启Frame模式需要重写- (CGSize)sizeThatFits,
    如下:
    -(CGSize)sizeThatFits:(CGSize)size{
    return CGSizeMake(size.width, A+B+C+D+E+....);
    }
3. SDAutoLayout相关

比masonry易用性更强,对view,tableView等视图的约束更加便捷,UILabel,UIButton,UIScrollView都有相应的约束方法。
类似的链式编码 很简洁,同时对Cell高度自适应效果也很好,并且有高度缓存。

  • 基本使用
    self.view0 = [[UIView alloc]init];
    self.view1 = [[UIView alloc]init];
    self.view2 = [[UIView alloc]init];
    self.view3 = [[UIView alloc]init];
    self.view4 = [[UIView alloc]init];

    self.view1.sd_layout
    .leftSpaceToView(self.view0,10)
    .topEqualToView(self.view0)
    .heightRatioToView(self.view0,0.5)
    .widthIs(60);
    
    self.view3.sd_layout
    .leftSpaceToView(self.view0,10)
    .topSpaceToView(self.view1,0)
    .widthRatioToView(self.view1,1)
    .heightRatioToView(self.view0,0.5);
    
    self.view4.sd_layout
    .centerXEqualToView(self.view0)
    .centerYEqualToView(self.view0)
    .widthRatioToView(self.view0,0.5)
    .autoHeightRatio(1);
    //添加多个子视图
    [self.view sd_addSubviews:@[_view0,_view1,_view2,_view3,_view4]];
    
    //修改约束后要更新父图及子视图的约束
     [UIView animateWithDuration:0.5 animations:^{
        self.view0.sd_layout
        .widthRatioToView(self.view,_widthRatio);
     
        //一定要更新约束,否则没效果
        [self.view0 updateLayout];
        //如果不更新子视图,则子视图没有动画效果
        [self.view5 updateLayout];
        //也可以写成下面这样生新而局子视图
        //[self.view0 layoutSubviews];
     }];
  • 普通View,Label 和 button 的约束
//view0有两个子视图
self.view0.sd_layout
    .topSpaceToView(self.view,10)
    .leftSpaceToView(self.view,10)
    .rightSpaceToView(self.view,10);
    [self.view0 sd_addSubviews:@[self.view1,self.view2]];
    
    self.view1.sd_layout
    .topSpaceToView(self.view0,10)
    .leftSpaceToView(self.view0,10)
    .rightSpaceToView(self.view0,10)
    .autoHeightRatio(0);       //view1 为UILabel类型,自适应高度
    
    self.view2.sd_layout           
    .rightEqualToView(self.view1)
    .leftEqualToView(self.view1)
    .topSpaceToView(self.view1,10)
    .heightIs(30);
    //设置view或Cell 高度自适应 
    [self.view0 setupAutoHeightWithBottomView:self.view2 bottomMargin:10];  
  
    //单行label 自适应宽度
    self.view4.text = @"Label的宽度自适应的测试";
    self.view4.sd_layout
    .leftSpaceToView(self.view,10)
    .topSpaceToView(self.view3,10)
    .heightIs(30);
    //设置单行Label自适应的最大宽度
    [self.view4 setSingleLineAutoResizeWithMaxWidth:300];

    //button的自适应高度
    //A:
   [self.view3 setTitle:@"这是关于button的宽度自适应" forState:UIControlStateNormal];
    self.view3.sd_layout
    .centerXEqualToView(self.view)
    .topSpaceToView(self.view0,10);
    //设置button单行文字自适应padding为左右边距
    [self.view3 setupAutoSizeWithHorizontalPadding:10 buttonHeight:30];
    //B:
    UIButton *button = [[UIButton alloc]init];
    self.button = button ;
    [button setImage:[UIImage imageNamed:@"test0.jpg"] forState:UIControlStateNormal];
    [button setTitle:@"这是一个文字" forState:UIControlStateNormal];
    button.backgroundColor = [UIColor grayColor];
    button.titleLabel.backgroundColor = [UIColor redColor];//文字默认颜色可能为白色
    button.titleLabel.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:button];
     
    button.sd_layout
    .topSpaceToView(self.view,10)
    .centerXEqualToView(self.view)
    .widthRatioToView(self.view,0.5)
    .autoHeightRatio(1);
    [self.view addSubview:button];
 
   //设置样式
    button.imageView.sd_layout
    .topSpaceToView(button,10)
    .centerXEqualToView(button)
    .widthRatioToView(button,0.8)
    .heightRatioToView(button,0.6);
    
    button.titleLabel.sd_layout
    .topSpaceToView(button.imageView,10)
    .rightSpaceToView(button,10)
    .leftSpaceToView(button,10)
    .bottomSpaceToView(button,10);
  • 生成与collectionView类似效果
 UIView *view0 = [[UIView alloc]init];
    [self.view addSubview:view0];
    self.view0 = view0;
    view0.backgroundColor = [UIColor yellowColor];
    view0.sd_layout
    .leftSpaceToView(self.view,10)
    .rightSpaceToView(self.view,10)
    .topSpaceToView(self.button,10);
    
    NSMutableArray *arr = [NSMutableArray array];
    for (int i = 0; i<count; i++) {
        UIView *view = [[UIView alloc]init];
        [arr addObject:view];
        view.backgroundColor = [UIColor blueColor];
        [view0 addSubview:view]; 
        view.sd_layout.autoHeightRatio(0.3);
    }
    
    //子视图只设置高宽比例,
    //用下面两种方法可生成宽间距或等宽的view
    [view0 setupAutoMarginFlowItems:arr
               withPerRowItemsCount:3
                          itemWidth:100
                     verticalMargin:10
                  verticalEdgeInset:5 
                horizontalEdgeInset:5];
//    [view0 setupAutoWidthFlowItems:arr
//              withPerRowItemsCount:3
//                    verticalMargin:10
//                  horizontalMargin:10
//                 verticalEdgeInset:5 
//               horizontalEdgeInset:5];
  • ScrollView的约束1
 UIScrollView *scrollView = [[UIScrollView alloc]init];
 [self.view addSubview:scrollView];
 scrollView.sd_layout.spaceToSuperView(UIEdgeInsetsZero);
  [scrollView sd_addSubviews:@[_view0,_view1,_view2,_view3]];
    
    self.view0.sd_layout
    .topSpaceToView(scrollView,50)
    .centerXEqualToView(scrollView)
    .widthIs(200)
    .heightEqualToWidth();
    
    self.view1.sd_layout
    .topSpaceToView(self.view0,100)
    .leftSpaceToView(scrollView,30)
    .rightSpaceToView(scrollView, 30)
    .heightIs(100);
    
    self.view2.sd_layout
    .topSpaceToView(self.view1,100)
    .rightSpaceToView(scrollView,60)
    .leftSpaceToView(scrollView,60)
    .autoHeightRatio(0.4);
    
   self.view3.sd_layout
    .topSpaceToView(self.view2,100)
    .rightSpaceToView(scrollView,100)
    .leftSpaceToView(scrollView,100)
    .heightIs(100);
 
  [scrollView setupAutoContentSizeWithBottomView:self.view3 bottomMargin:10];
  • ScrollView的约束2
 UIView *contentView = [[UIView alloc]init];
 contentView.backgroundColor = [UIColor whiteColor];  
[self.scrollView addSubview:contentView];
    
    contentView.sd_layout
    .topSpaceToView(self.scrollView,0)
    .leftSpaceToView(self.scrollView,0)
    .rightEqualToView(self.scrollView);
    
    NSMutableArray *arr  = [NSMutableArray array];
    for (int i= 0; i < 100; i++) {
        UIView *view = [[UIView alloc]init];
        view.backgroundColor = [self randomColor];
        [contentView addSubview:view];
        view.sd_layout.autoHeightRatio(1);
        [arr addObject:view];
    }
    [contentView setupAutoWidthFlowItems:arr
                    withPerRowItemsCount:5
                          verticalMargin:10
                        horizontalMargin:10
                       verticalEdgeInset:10
                     horizontalEdgeInset:10 ];
//    [contentView setupAutoMarginFlowItems:arr
//                     withPerRowItemsCount:5
//                                itemWidth:50
//                           verticalMargin:10
//                        verticalEdgeInset:10
//                      horizontalEdgeInset:10 ];
    
    //如果scrollView 中子视图也要自适应则这样处理合适
    //将所有视图放到contentView中
    [self.scrollView setupAutoContentSizeWithBottomView:contentView bottomMargin:10];
  • TableViewCell 的约束
//第一步设置正确的cell 约束
    UIView *view0 = [UIView new];
    view0.backgroundColor = [UIColor redColor];
    UIView *view1 = [UIView new];
    UILabel *lable = [UILabel new];
    UIView *view3 = [UIView new];
    /*******
     一定要先将视图添加到父视图后再添加约束,否则可能无效
     ********/
    [self.contentView sd_addSubviews:@[view0,view1,lable,view3,view4,view5]];

    view0.sd_layout
    .topSpaceToView(self.contentView,10)
    .leftSpaceToView(self.contentView,10)
    .widthIs(50)
    .heightIs(50);
    
    view1.sd_layout
    .topEqualToView(view0)
    .leftSpaceToView(view0,10)
    .rightSpaceToView(self.contentView,10)
    .heightIs(30);
    
    lable.sd_layout
    .leftEqualToView(view1)
    .topSpaceToView(view1,10)
    .rightSpaceToView(self.contentView,120)
    .autoHeightRatio(0);

    view3.sd_layout
    .leftSpaceToView(lable,10)
    .topSpaceToView(view1,10)
    .rightSpaceToView(self.contentView,10)
    .heightRatioToView(lable,1);
    //设置cell 高度自适应
    [self setupAutoHeightWithBottomView:view4 bottomMargin:10];

 //第二步代理方法返回Cell高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return     //推荐写法
 [self.tableView cellHeightForIndexPath:indexPath                                        model:self.dataSource[indexPath.row]
                                  keyPath:@"text"
                                cellClass:[DemoVC7Cell class]
                         contentViewWidth:[UIScreen mainScreen].bounds.size.width];
    /*
    //数据量小时可以这样写
    return
 [self.tableView cellHeightForIndexPath:indexPath 
                    cellContentViewWidth:[UIScreen mainScreen].bounds.size.width tableView:tableView];
     */
}

高度缓存

-(UITableViewCell *)tableView:(UITableView *)tableView 
           cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 //
//
//缓存高度,tableview滑动更加流畅
 [cell useCellFrameCacheWithIndexPath:indexPath tableView:tableView];
//
//
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,302评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,563评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,433评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,628评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,467评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,354评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,777评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,419评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,725评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,768评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,543评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,387评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,794评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,032评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,305评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,741评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,946评论 2 336

推荐阅读更多精彩内容