自適應TableViewCell(純代碼)

前言:在iOS程序開發中,TableView的實用是最常見的,在一些比較特殊的需求下,必須展示的是用戶評論信息,或發布的微博,這樣的情況下,固定高度的cell顯然是不能實現我們的需求,這就需要我們根據需要展示的內容,動態的設置cell的高度.下面是我做的一個Demo, 我們一起來做一下如何去實現這樣的功能,希望能夠對你起到一定的幫助.下面是效果圖.

圖1.gif

1 . 首先來我們分析一下這個需求,很顯然這是一個可以滑動的列表,很自然我們就會想到用tableView去實現.在這個列表上面,每一個cell存放一條用戶發送的數據,這些數據包括用戶的名字,用戶發送的正文內容,另外就是有一些是有配圖的,有一些是沒配圖的.另外就是單元格的高度會隨著內容的變化而變大或者變小.分析完這些,那我們開始擼代碼,既然我們沒有做過自適應高度的需求,那我們總做過高度固定的單元格吧,那就索性先給一個固定高度,然后再去調整. 接著我們去創建viewController.并且給tableView注冊自定義單元格.

    self.tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
    [self.tableView registerClass:[AdaptiveTableViewCell class] forCellReuseIdentifier:identifier];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];

2 . 創建model類,添加數據源,并且保存在數組中.這個數據源我是寫在了,plist文件當中,并且使用cocoaPods導入MJExtension進行數據轉模型.

#pragma mark - 懶加載
- (NSArray *)dataSource {
    if (!_dataSource) {
        self.dataSource = [AdaptiveModel mj_objectArrayWithFilename:@"ModelList.plist"];
    }
    return _dataSource;
}

3 . 在自定義的cell中添加重寫初始化方法,添加子控件.

// 重寫初始化方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self setupView];
    }
    return self;
}

// 添加子控件
- (void)setupView {
    UILabel *nameLabel = [UILabel new];
    [self.contentView addSubview:nameLabel];
    nameLabel.textColor = [UIColor orangeColor];
    nameLabel.font = [UIFont systemFontOfSize:17];
    self.nameLabel = nameLabel;
    
    UILabel *textLabel = [[UILabel alloc] init];
    textLabel.numberOfLines = 0;
    textLabel.font = [UIFont systemFontOfSize:14];
    [self.contentView addSubview:textLabel];
    self.text_Label = textLabel;
    
    UIImageView *pictureView = [[UIImageView alloc] init];
    [self.contentView addSubview:pictureView];
    self.picthreView = pictureView;
}

4 . 注意在添加子控件的時候我是沒有給出控件的frame的.因為單元格的高度要根據需要展示的內容來動態計算的,那我們就在model類里面動態的計算出控件的framecell的高度,并且保存在model類中. 注意在model中要把#import <Foundation/Foundation.h>框架更改成#import <UIKit/UIKit.h>否則沒法添加CGRect屬性.

#import <UIKit/UIKit.h>
// 模型
@interface AdaptiveModel : NSObject

@property (nonatomic, copy) NSString *name;         // 昵稱
@property (nonatomic, copy) NSString *text;         // 正文
@property (nonatomic, copy) NSString *picture;      // 圖片

@property (nonatomic, assign) CGRect nameFrame;     // 昵稱的frame
@property (nonatomic, assign) CGRect textFrame;     // 正文的frame
@property (nonatomic, assign) CGRect pictureFrame;  // 圖片的frame
@property (nonatomic, assign) CGFloat cellHeight;    // 單元格高度

@end

5 .然后再model.m中懶加載計算出各個控件的framecell的高度

#import "AdaptiveModel.h"
#define Space 10          // 間距
@implementation AdaptiveModel

// 懶加載
- (CGFloat)cellHeight {
    if (_cellHeight == 0) {
        CGFloat nameX = Space;
        CGFloat namey = Space;
        
        // 獲取文字寬度
        //    CGSize nameSzie = [self getLabalSizeWithLabel:self.nameLabel];
        NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:17]};
        CGSize nameSize = [self.name sizeWithAttributes:attribute];
        self.nameFrame = CGRectMake(nameX, namey, nameSize.width, nameSize.height);
        // 正文
        CGFloat textW = [UIScreen mainScreen].bounds.size.width - Space * 2;
        NSDictionary *attribute1 = @{NSFontAttributeName: [UIFont systemFontOfSize:14]};
        CGSize textsize =  [self.text boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attribute1 context:nil].size;
        //    CGFloat textH = [self getLabelSizeWithLabel:self.text_Label width:textW];
        self.textFrame = CGRectMake(Space, CGRectGetMaxY(self.nameFrame) + Space, textW, textsize.height);
        // 圖片
        if (self.picture) {
            self.pictureFrame = CGRectMake(Space, CGRectGetMaxY(self.textFrame) + Space, 100, 100);
            _cellHeight = CGRectGetMaxY(self.pictureFrame) + Space;
        } else {
            _cellHeight = CGRectGetMaxY(self.textFrame) + Space;
        }
    }
    return _cellHeight;
}

@end

注意事項:
注意在此時用到了2個方法,第一個是獲取文字尺寸,這個方法僅限于label沒有換行,需要獲取文字寬度時使用.需要注意的地方就是設置的font和你label控件設置的font必須是一致的.

  // 獲取文字寬度
        NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:17]};
        CGSize nameSize = [self.name sizeWithAttributes:attribute];

第二個方法也是獲取文字尺寸,和第一個方法不同的是這個是可以換行的,需要注意的是不僅要設置font和你設置的labelfont必須是一致的,還要給它設置一個最大的寬度,告訴它最大寬度時多少,才會自動換行.

  // 正文
        CGFloat textW = [UIScreen mainScreen].bounds.size.width - Space * 2;
        NSDictionary *attribute1 = @{NSFontAttributeName: [UIFont systemFontOfSize:14]};
        CGSize textsize =  [self.text boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attribute1 context:nil].size;

6 .接下來我們計算好了cell的高度,就在tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath這個方法中設置cell的高度就可以了.

// 設置單元格高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    AdaptiveModel *model = self.dataSource[indexPath.row];
    return model.cellHeight;
}

7 . 設置單元格,給單元格上的控件賦值

// 設置單元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    AdaptiveTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
    // 傳遞數組模型
    cell.model = self.dataSource[indexPath.row];
    return cell;
}

8 .在自定義的cell里面重寫屬性的setter方法,給子控件賦值,并且設置控件的frame

// 重寫屬性的setter方法
- (void)setModel:(AdaptiveModel *)model {
    if (_model != model) {
        _model = model;
    }
    self.nameLabel.text = model.name;
    self.text_Label.text = model.text;
    if (model.picture) { // 有圖片
        self.picthreView.hidden = NO;
        self.picthreView.image = [UIImage imageNamed:model.picture];
    } else {            // 沒有圖片
        self.picthreView.hidden = YES;
    }
    // 設置控件的frame
    self.nameLabel.frame = self.model.nameFrame;
    self.text_Label.frame = self.model.textFrame;
    self.picthreView.frame = self.model.pictureFrame;
}

總結:以上就是自適應TableViewCell的全過程,我們可以得出以下的結論,要想去實現tableView自適應高度,首先我們需要計算出model中各個控件的frame和所需要的cell的高度.然后再設置單元格高度的方法中,設置單元格所需要的高度.最后再把各個控件的frame傳遞到cell中來設置.

當然還有其他的實現方法, 我這里只是給出了一個思路,具體怎么實現,還需要你自己去動腦子思考,希望能夠對你起到一定的幫助作用.

另附gitHub下載地址

下一篇:自適應TableViewCell(XIB)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 概述在iOS開發中UITableView可以說是使用最廣泛的控件,我們平時使用的軟件中到處都可以看到它的影子,類似...
    liudhkk閱讀 9,090評論 3 38
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,245評論 4 61
  • 最近不忙才想起來要好好整理之前的項目了。誠然其中遇到了許許多多得問題,但是當時都是沒有太多的去關注,現想起來真是浪...
    Hflydragon閱讀 166評論 0 0
  • 也許每一個男子全都有過這樣的兩個女人,至少兩個。娶了紅玫瑰,久而久之,紅的變成了墻上的一抹蚊子血,白的還是“床前明...
    簡單談談閱讀 273評論 0 0
  • 寫點什么呢?今天才是第三天。都已經有了不知道該說什么的感覺了。寫自己身邊發生的事吧,又覺得身邊的事太小,不值...
    谷喵兒閱讀 274評論 0 0