前兩天做了一個項目,中間有遇到一個問題,就是聊天的時候cell高度的問題。這是一個很多前輩都遇到過,並且很完美的解決過的問題。這裡主要是記錄自己的學習心得。項目中首先想到的是用三方庫,可是有問題,遂放棄,自己寫一個,但是沒有封裝。項目地址 UITableView 的屬性特征什麼的,這裡就暫時不做介紹 ...
前兩天做了一個項目,中間有遇到一個問題,就是聊天的時候cell高度的問題。這是一個很多前輩都遇到過,並且很完美的解決過的問題。這裡主要是記錄自己的學習心得。項目中首先想到的是用三方庫,可是有問題,遂放棄,自己寫一個,但是沒有封裝。項目地址
UITableView 的屬性特征什麼的,這裡就暫時不做介紹了。
由於聊天內容比較簡單,不需要對聊天做出很多操作,只是簡單的使用 UILable 進行展示即可。首先我們定義一個模型 JXChatModel
// // JXChatModel.h // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // #import <UIKit/UIKit.h> @interface JXChatModel : NSObject // 字典模型轉換 + (instancetype)modelWithDict:(NSDictionary *)dict; /** 昵稱 */ @property (nonatomic,copy) NSString * nickName; /** 等級 */ @property (nonatomic,copy) NSString * graide; /** 內容 */ @property (nonatomic,copy) NSString * content; /** 高度,用來存放計算後的cell高度 */ @property (nonatomic,assign) CGFloat cellHeight; @end
// // JXChatModel.m // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // #import "JXChatModel.h" @implementation JXChatModel + (instancetype)modelWithDict:(NSDictionary *)dict { JXChatModel * model = [[self alloc] init]; [model setValuesForKeysWithDictionary:dict]; return model; } - (void)setValue:(id)value forUndefinedKey:(NSString *)key { // 這裡對沒有定義的鍵值對不進行任何操作 } @end
- 自定義 UITableViewCell
前面我們定義了一個數據模型,當我們請求過來的數據之後,我們首先將數據轉換成模型,之後直接將模型賦值給我們自定義的表格,這樣做有極大的好處
// // JXChatCell.h // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // #import <UIKit/UIKit.h> @class JXChatModel; @interface JXChatCell : UITableViewCell /** 模型 */ @property (nonatomic,strong) JXChatModel * model; @end
// // JXChatCell.m // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // #import "JXChatCell.h" #import "JXChatModel.h" #import "Masonry.h" /** 等級圖片寬度 */ #define kIconWidth 25 /** 等級圖片高度 */ #define kIconHeight 25 #define kWidth [UIScreen mainScreen].bounds.size.width @interface JXChatCell () /** 頭像 */ @property (nonatomic,weak) UIImageView * iconImageView; /** 昵稱 */ @property (nonatomic,weak) UILabel * nickNameLabel; /** 內容 */ @property (nonatomic,weak) UILabel * contentLabel; @end @implementation JXChatCell - (void)setModel:(JXChatModel *)model { NSString * name = [NSString stringWithFormat:@"rank_%@",model.graide]; self.iconImageView.image = [UIImage imageNamed:name]; self.nickNameLabel.text = model.nickName; [self.nickNameLabel sizeToFit]; CGRect frame = self.nickNameLabel.frame; frame.size.height = kIconHeight; self.nickNameLabel.frame = frame; // 設置內容寬度,這裡首先在自適應之前需要將內容的寬度固定 self.contentLabel.text = model.content; CGRect contentFrame = self.nickNameLabel.frame; contentFrame.size.width = kWidth - kIconWidth - self.nickNameLabel.frame.size.width - 80; self.contentLabel.frame = contentFrame; [self.contentLabel sizeToFit]; model.cellHeight = CGRectGetMaxY(self.contentLabel.frame) + 10; } #pragma mark - 佈局 - (void)layoutSubviews { [super layoutSubviews]; // 等級圖片 self.iconImageView.frame = CGRectMake(5, 0, kIconWidth, kIconHeight); // 昵稱 self.nickNameLabel.frame = CGRectMake(kIconWidth + 10 , 0, self.nickNameLabel.frame.size.width, kIconHeight); // 內容大小 self.contentLabel.frame = CGRectMake(CGRectGetMaxX(self.nickNameLabel.frame) + 5, 5, self.contentLabel.frame.size.width, self.contentLabel.frame.size.height); } #pragma mark - 懶載入 - (UIImageView *)iconImageView{ if (_iconImageView == nil) { UIImageView * iconImageView = [[UIImageView alloc] init]; [self.contentView addSubview:iconImageView]; _iconImageView = iconImageView; } return _iconImageView; } - (UILabel *)nickNameLabel{ if (_nickNameLabel == nil) { UILabel * nickNameLabel = [[UILabel alloc] init]; nickNameLabel.textColor = [UIColor orangeColor]; nickNameLabel.font = [UIFont systemFontOfSize:13.0]; [self.contentView addSubview:nickNameLabel]; _nickNameLabel = nickNameLabel; } return _nickNameLabel; } - (UILabel *)contentLabel{ if (_contentLabel == nil) { UILabel * contentLabel = [[UILabel alloc] init]; contentLabel.textColor = [UIColor blackColor]; contentLabel.numberOfLines = 0; contentLabel.font = [UIFont systemFontOfSize:13.0]; [self.contentView addSubview:contentLabel]; _contentLabel = contentLabel; } return _contentLabel; } @end
- 控制器部分代碼
在控制器中我們需要操作的就稍微少了點了,這裡我們只需要將數據請求下來,然後將數據轉換成模型,存到數組中。之後的 UITableView 數據源就根據這個數組來操作
// // ViewController.m // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // 自動計算行高 #import "ViewController.h" #import "JXChatCell.h" #import "JXChatModel.h" @interface ViewController ()<UITableViewDelegate,UITableViewDataSource> /** 數據源數組 */ @property (nonatomic,strong) NSMutableArray * chatArray; /** UITableView */ @property (nonatomic,weak) UITableView * tableView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 數據 NSArray * array = @[ @{ @"nickName":@"你成佛了", @"graide":@"16", @"content":@"連接方式李金髮歐式24234242342馮紹峰煩死拉伸的減肥了敬愛是驕傲是激發按時發放費;啊; 拉伸放假接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"了仨解放啦", @"graide":@"6", @"content":@"連接方式沙發沙發" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"式李金髮", @"graide":@"13", @"content":@"連接方式接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放323242342432圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法來釋放" }, @{ @"nickName":@"垃圾費垃圾房間", @"graide":@"1", @"content":@"連接方式李反對黨的圾費垃圾房間愛亂收費;啊; 拉伸放假啊;發;是放假啊;瞭解演算法lkjslajflsajflasjlasjflajflj零距離聖誕節佛按實際大量積分垃圾地方啦垃圾了房間愛令肌膚拉伸件地方垃圾垃圾了極大浪費就暗戀的激發了設計費垃圾費拉激發偶爾加亂收費來釋放" } ]; // 將數據轉換成模型 for (NSDictionary * dict in array) { JXChatModel * model = [JXChatModel modelWithDict:dict]; [self.chatArray addObject:model]; } [self.tableView reloadData]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.chatArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString * identifier = @"cell"; JXChatCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (cell == nil) { cell = [[JXChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } cell.model = self.chatArray[indexPath.row]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { JXChatModel * model = self.chatArray[indexPath.row]; return model.cellHeight; } // 先給cell表格一個預估計高度 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { return 100; } - (NSMutableArray *)chatArray{ if (_chatArray == nil) { _chatArray = [NSMutableArray array]; } return _chatArray; } - (UITableView *)tableView{ if (_tableView == nil) { UITableView * tableView = [[UITableView alloc] init]; tableView.frame = self.view.bounds; tableView.delegate = self; tableView.dataSource = self; [self.view addSubview:tableView]; _tableView = tableView; } return _tableView; } @end
構建運行,展示效果