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閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容