//// MJMessage.m#import "MJMessage.h"@implementation MJMessage+ (instancetype)messageWithDict:(NSDictionary *)dict{ return [[self alloc] initWithDict:dict];}- (instancetype)initWithDict:(NSDictionary *)dict{ if (self = [super init]) { [self setValuesForKeysWithDictionary:dict]; } return self;}@end
//// MJMessage.h#import <Foundation/Foundation.h>typedef enum { MJMessageTypeMe = 0, // 自己发的 MJMessageTypeOther // 别人发的} MJMessageType;@interface MJMessage : NSObject/** * 聊天内容 */@property (nonatomic, copy) NSString *text;/** * 发送时间 */@property (nonatomic, copy) NSString *time;/** * 信息的类型 */@property (nonatomic, assign) MJMessageType type;+ (instancetype)messageWithDict:(NSDictionary *)dict;- (instancetype)initWithDict:(NSDictionary *)dict;@end
//// MJMessageFrame.h// 正文的字体#define MJTextFont [UIFont systemFontOfSize:15]#import <Foundation/Foundation.h>@class MJMessage;@interface MJMessageFrame : NSObject/** * 头像的frame */@property (nonatomic, assign, readonly) CGRect iconF;/** * 时间的frame */@property (nonatomic, assign, readonly) CGRect timeF;/** * 正文的frame */@property (nonatomic, assign, readonly) CGRect textF;/** * cell的高度 */@property (nonatomic, assign, readonly) CGFloat cellHeight;/** * 数据模型 */@property (nonatomic, strong) MJMessage *message;@end
//// MJMessageFrame.m#import "MJMessageFrame.h"#import "MJMessage.h"@implementation MJMessageFrame/** * 计算文字尺寸 * * @param text 需要计算尺寸的文字 * @param font 文字的字体 * @param maxSize 文字的最大尺寸 */- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize{ NSDictionary *attrs = @{NSFontAttributeName : font}; return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;}- (void)setMessage:(MJMessage *)message{ _message = message; // 间距 CGFloat padding = 10; // 屏幕的宽度 CGFloat screenW = [UIScreen mainScreen].bounds.size.width; // 1.时间 CGFloat timeX = 0; CGFloat timeY = 0; CGFloat timeW = screenW; CGFloat timeH = 40; _timeF = CGRectMake(timeX, timeY, timeW, timeH); //因为timeF属性是readonly的所以没有自动生成set方法 所以不能用点语法 所以用_timeF // 2.头像 CGFloat iconY = CGRectGetMaxY(_timeF); //头像的y值就是时间的最大Y值 CGFloat iconW = 40; CGFloat iconH = 40; CGFloat iconX; if (message.type == MJMessageTypeOther) {// 别人发的 iconX = padding; } else { // 自己的发的 iconX = screenW - padding - iconW; } _iconF = CGRectMake(iconX, iconY, iconW, iconH); // 3.正文 CGFloat textY = iconY; // 文字的尺寸 CGSize textMaxSize = CGSizeMake(150, MAXFLOAT); //文字不限高度 ,要限制宽度 CGSize textSize = [self sizeWithText:message.text font:MJTextFont maxSize:textMaxSize]; CGFloat textX; if (message.type == MJMessageTypeOther) {// 别人发的 textX = CGRectGetMaxX(_iconF) + padding; } else {// 自己的发的 textX = iconX - padding - textSize.width; }// _textF = CGRectMake(textX, textY, textSize.width, textSize.height); _textF = (CGRect){{textX, textY}, textSize}; // 4.cell的高度 CGFloat textMaxY = CGRectGetMaxY(_textF); CGFloat iconMaxY = CGRectGetMaxY(_iconF); _cellHeight = MAX(textMaxY, iconMaxY) + padding; //正文和头像的最大Y值的较大者加上间距就是cell的高度}@end
2.3.2自定义cell
//// MJMessageCell.h//#import <UIKit/UIKit.h>@class MJMessageFrame;@interface MJMessageCell : UITableViewCell+ (instancetype)cellWithTableView:(UITableView *)tableView;@property (nonatomic, strong) MJMessageFrame *messageFrame;@end
//// MJMessageCell.m#import "MJMessageCell.h"#import "MJMessageFrame.h"#import "MJMessage.h"@interface MJMessageCell()/** * 时间 */@property (nonatomic, weak) UILabel *timeView;/** * 头像 */@property (nonatomic, weak) UIImageView *iconView;/** * 正文 */@property (nonatomic, weak) UIButton *textView;@end@implementation MJMessageCell+ (instancetype)cellWithTableView:(UITableView *)tableView{ static NSString *ID = @"message"; MJMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[MJMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } return cell;}- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // 子控件的创建和初始化 // 1.时间 UILabel *timeView = [[UILabel alloc] init]; //因为这个属性定义的是弱指针类型的 所以这行代码过后就会被销毁 所以先用一个强指针指向刚创建的这个对象然后把它添加到contentView中// timeView.backgroundColor = [UIColor redColor]; timeView.textAlignment = NSTextAlignmentCenter; timeView.textColor = [UIColor grayColor]; timeView.font = [UIFont systemFontOfSize:13]; [self.contentView addSubview:timeView]; //把刚创建的那个lable对象添加到contentView中 self.timeView = timeView; // 2.头像 UIImageView *iconView = [[UIImageView alloc] init]; [self.contentView addSubview:iconView]; self.iconView = iconView; // 3.正文 UIButton *textView = [[UIButton alloc] init]; textView.titleLabel.numberOfLines = 0; // 自动换行 textView.backgroundColor = [UIColor purpleColor]; textView.titleLabel.font = MJTextFont; [self.contentView addSubview:textView]; self.textView = textView; // 4.设置cell的背景色 self.backgroundColor = [UIColor clearColor]; } return self;}- (void)setMessageFrame:(MJMessageFrame *)messageFrame{ _messageFrame = messageFrame; MJMessage *message = messageFrame.message; // 1.时间 self.timeView.text = message.time; self.timeView.frame = messageFrame.timeF; // 2.头像 NSString *icon = (message.type == MJMessageTypeMe) ? @"me" : @"other"; self.iconView.image = [UIImage imageNamed:icon]; self.iconView.frame = messageFrame.iconF; // 3.正文 [self.textView setTitle:message.text forState:UIControlStateNormal]; self.textView.frame = messageFrame.textF;}@end
2.3.3控制器
//// MJViewController.m#import "MJViewController.h"#import "MJMessage.h"#import "MJMessageFrame.h"#import "MJMessageCell.h"@interface MJViewController () <UITableViewDataSource, UITableViewDelegate>@property (weak, nonatomic) IBOutlet UITableView *tableView;@property (nonatomic, strong) NSMutableArray *messageFrames;@end@implementation MJViewController- (void)viewDidLoad{ [super viewDidLoad]; // 设置背景色和去除分割线 self.tableView.backgroundColor = [UIColor colorWithRed:235/255.0 green:235/255.0 blue:235/255.0 alpha:1.0]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;}- (BOOL)prefersStatusBarHidden{ return YES;}- (NSMutableArray *)messageFrames{ if (_messageFrames == nil) { NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil]]; NSMutableArray *mfArray = [NSMutableArray array]; for (NSDictionary *dict in dictArray) { // 消息模型 MJMessage *msg = [MJMessage messageWithDict:dict]; // frame模型 MJMessageFrame *mf = [[MJMessageFrame alloc] init]; mf.message = msg; // 添加模型 [mfArray addObject:mf]; } _messageFrames = mfArray; } return _messageFrames;}#pragma mark - 数据源方法- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.messageFrames.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ // 1.创建cell MJMessageCell *cell = [MJMessageCell cellWithTableView:tableView]; // 2.给cell传递模型 cell.messageFrame = self.messageFrames[indexPath.row]; // 3.返回cell return cell;}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ MJMessageFrame *mf = self.messageFrames[indexPath.row]; return mf.cellHeight;}@end