美文网首页实用技术
UITableViewCell高度自适应

UITableViewCell高度自适应

作者: wpf_register | 来源:发表于2017-02-06 10:43 被阅读140次

    参考文档

    比较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];
    //
    //
    }
    

    相关文章

      网友评论

      本文标题:UITableViewCell高度自适应

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