素材有两个一个消息字典,一个自动回复匹配字典
首先字典转模型,位置和数据都是模型里面弄好的 加了一个工具方法resizeImage来调整聊天界面
然后来写自定义cell
最后在控制器里面写逻辑
// // UIImage+resizeImage.h // QQ聊天 // // Created by YaguangZhu on 15/8/28. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import <UIKit/UIKit.h> @interface UIImage (resizeImage) + (UIImage *)resizeWithImageName:(NSString *)name; @end ---------------------------------// // UIImage+resizeImage.m // QQ聊天 // // Created by YaguangZhu on 15/8/28. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import "UIImage+resizeImage.h" @implementation UIImage (resizeImage) //返回一个可拉伸的图片 + (UIImage *)resizeWithImageName:(NSString *)name { UIImage *normal = [UIImage imageNamed:name]; CGFloat w = normal.size.width * 0.5f -1; CGFloat h = normal.size.height *0.5f -1; //CGFloat w = normal.size.width*0.8; // CGFloat h = normal.size.height*0.8; //传入上下左右不需要拉升的编剧,只拉伸中间部分 return [normal resizableImageWithCapInsets:UIEdgeInsetsMake(h, w, h, w)]; // [normal resizableImageWithCapInsets:UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)] // 1 = width - leftCapWidth - right // 1 = height - topCapHeight - bottom //传入上下左右不需要拉升的编剧,只拉伸中间部分,并且传入模式(平铺/拉伸) // [normal :<#(UIEdgeInsets)#> resizingMode:<#(UIImageResizingMode)#>] //只用传入左边和顶部不需要拉伸的位置,系统会算出右边和底部不需要拉升的位置。并且中间有1X1的点用于拉伸或者平铺 // 1 = width - leftCapWidth - right // 1 = height - topCapHeight - bottom // return [normal stretchableImageWithLeftCapWidth:w topCapHeight:h]; } @end
// // Constant.h // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #ifndef QQ___Constant_h #define QQ___Constant_h #define bScreenWidth [[UIScreen mainScreen] bounds].size.width #define bNormalH 44 #define bIconW 50 #define bIconH 50 #define bBtnFont [UIFont systemFontOfSize:15.0f] #endif
// // HMMessageModel.h // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import <Foundation/Foundation.h> typedef enum { HMMessageModelGatsby =0, HMMessageModelJobs }HMMessageModeltype; @interface HMMessageModel : NSObject @property(nonatomic,copy) NSString *text; @property(nonatomic,copy) NSString *time; @property(nonatomic,assign) HMMessageModeltype type; @property(nonatomic,assign)BOOL hideTime; - (instancetype)initWithDict:(NSDictionary *)dict; + (instancetype)messageWithDict:(NSDictionary *)dict; //+ (NSArray *)Messages; @end ---------------------------------// // HMMessageModel.m // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import "HMMessageModel.h" @implementation HMMessageModel - (instancetype)initWithDict:(NSDictionary *)dict { self = [super init]; if (self) { [self setValuesForKeysWithDictionary:dict]; } return self; } + (instancetype)messageWithDict:(NSDictionary *)dict { return [[self alloc] initWithDict:dict]; } //+ (NSArray *)Messages //{ // NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil]]; // NSMutableArray *arrayM = [NSMutableArray array]; // for (NSDictionary *dict in array) { // [arrayM addObject:[self messageWithDict:dict]]; // } // // return arrayM; //} @end
// // HMMessageFrameModel.h // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @class HMMessageModel; @interface HMMessageFrameModel : NSObject //时间的frame @property (nonatomic, assign,readonly)CGRect timeF; //正文的frame @property (nonatomic, assign,readonly)CGRect textViewF; //图片 @property (nonatomic, assign,readonly)CGRect iconF; //cell @property (nonatomic, assign)CGFloat cellH; //数据模型 @property (nonatomic, strong)HMMessageModel *message; + (NSArray *)messageFrame; @end --------------------------------- // // HMMessageFrameModel.m // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import "HMMessageFrameModel.h" #import "HMMessageModel.h" #import "Constant.h" @implementation HMMessageFrameModel - (void)setMessage:(HMMessageModel *)message { _message = message; CGFloat padding = 10; if (message.hideTime ==NO) { //1. 时间 CGFloat timeX = 0; CGFloat timeY = 0; CGFloat timeW = bScreenWidth; CGFloat timeH = bNormalH; _timeF = CGRectMake(timeX, timeY, timeW, timeH); } //2.头像 CGFloat iconX; CGFloat iconY = CGRectGetMaxY(_timeF); CGFloat iconW = bIconW; CGFloat iconH = bIconH; if (message.type == HMMessageModelGatsby) {//自己发的 iconX = bScreenWidth - iconW - padding; }else{//别人发的 iconX = padding; } _iconF = CGRectMake(iconX, iconY, iconW, iconH); //3.正文 CGFloat textX; CGFloat textY = iconY+padding; CGSize textMaxSize = CGSizeMake(150, MAXFLOAT); CGSize textRealSize = [message.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:bBtnFont} context:nil].size; CGSize btnSize = CGSizeMake(textRealSize.width+40, textRealSize.height+40); if (message.type == HMMessageModelGatsby) { textX = bScreenWidth - iconW - padding*2 - btnSize.width; }else{ textX = padding + iconW; } // _textViewF = CGRectMake(textX, textY, <#CGFloat width#>, <#CGFloat height#>) _textViewF = (CGRect){{textX,textY},btnSize}; //4.cell高度 CGFloat iconMaxY = CGRectGetMaxY(_iconF); CGFloat textMaxY = CGRectGetMaxY(_textViewF); _cellH = MAX(iconMaxY, textMaxY); } + (NSArray *)messageFrame { NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil]]; NSMutableArray *arrayM = [NSMutableArray array]; for (NSDictionary *dict in array) { // 要添加statusFrame对象 HMMessageFrameModel *frameModel = [[HMMessageFrameModel alloc] init]; // 实例化一个新的Status模型 HMMessageModel *messageModel = [HMMessageModel messageWithDict:dict]; HMMessageFrameModel *lastModel = [arrayM lastObject]; messageModel.hideTime = [messageModel.time isEqualToString:lastModel.message.time]; // 调用自己的setter方法,保存status数据模型,同时计算出所有控件的位置 frameModel.message = messageModel; // 将statusFrame添加到数组 [arrayM addObject:frameModel]; } return arrayM; } @end
// // HMMessageCell.h // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import <UIKit/UIKit.h> //@class HMMessageModel; @class HMMessageFrameModel; @interface HMMessageCell : UITableViewCell + (instancetype)messageCellWithTableView:(UITableView *)tableview; //@property(nonatomic,strong) HMMessageModel *messageModel; // frame 的模型 @property(nonatomic,strong) HMMessageFrameModel *frameModel; @end --------------------------------- // // HMMessageCell.m // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import "HMMessageCell.h" #import "HMMessageModel.h" #import "HMMessageFrameModel.h" #import "Constant.h" #import "UIImage+resizeImage.h" /** 姓名字体 */ #define kNameFont [UIFont systemFontOfSize:14] /** 正文字体 */ #define kTextFont [UIFont systemFontOfSize:16] @interface HMMessageCell() @property(nonatomic,strong)UILabel *time; @property(nonatomic,strong)UIButton *textView; @property(nonatomic,strong)UIImageView *icon; @end @implementation HMMessageCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:nil reuseIdentifier:nil]; self.backgroundColor = [UIColor clearColor]; return self; } + (instancetype)messageCellWithTableView:(UITableView *)tableview { static NSString *ID = @"messageCell"; HMMessageCell *cell = [tableview dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[self alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } return cell; } - (UILabel *)time { if (_time ==nil) { _time = [[UILabel alloc]init]; _time.textAlignment = NSTextAlignmentCenter; _time.font = [UIFont systemFontOfSize:13.0f]; [self.contentView addSubview:_time]; } return _time; } - (UIButton *)textView { if (_textView == nil) { _textView = [[UIButton alloc]init]; //_textView.backgroundColor = [UIColor grayColor]; _textView.titleLabel.font = bBtnFont; _textView.titleLabel.numberOfLines = 0;//自动换行 _textView.contentEdgeInsets = UIEdgeInsetsMake(20, 20, 20, 20); [_textView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [self.contentView addSubview:_textView]; } return _textView; } - (UIImageView *)icon { if (_icon ==nil) { _icon = [[UIImageView alloc] init]; [self.contentView addSubview:_icon]; } return _icon; } //可以通过数据模型来设置数据和位置,也可以通过位置模型来设置数据和位置 - (void)setFrameModel:(HMMessageFrameModel *)frameModel { _frameModel = frameModel; HMMessageModel *messageModel = frameModel.message; //1.时间 self.time.frame = frameModel.timeF; self.time.text = messageModel.time; //2.头像 self.icon.frame = frameModel.iconF; if (messageModel.type == HMMessageModelGatsby) { self.icon.image = [UIImage imageNamed:@"Gatsby"]; }else{ self.icon.image = [UIImage imageNamed:@"Jobs"]; } //3.正文 self.textView.frame = frameModel.textViewF; [self.textView setTitle:messageModel.text forState:UIControlStateNormal]; if (messageModel.type == HMMessageModelGatsby) { [self.textView setBackgroundImage:[UIImage resizeWithImageName:@"chat_send_nor"] forState:UIControlStateNormal]; }else { [self.textView setBackgroundImage:[UIImage resizeWithImageName:@"chat_recive_nor"] forState:UIControlStateNormal]; } } - (void)awakeFromNib { // Initialization code } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } @end
// // ViewController.h // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end ---------------------------------- // // ViewController.m // QQ聊天 // // Created by YaguangZhu on 15/8/27. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import "ViewController.h" #import "HMMessageModel.h" #import "HMMessageCell.h" #import "HMMessageFrameModel.h" @interface ViewController ()<UITabBarControllerDelegate,UITableViewDataSource,UITextFieldDelegate> //@property(nonatomic,strong) NSArray *messages; @property(nonatomic,strong) NSMutableArray *messagesFrame; @property (weak, nonatomic) IBOutlet UITextField *inputView; @property (weak, nonatomic) IBOutlet UITableView *tableView; //自动回复数组 @property (nonatomic, strong)NSDictionary *autoReplay; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.tableView.allowsSelection = NO; self.tableView.backgroundColor = [UIColor colorWithRed:225/255.0 green:225/255.0 blue:225/255.0 alpha:1.0]; self.tableView.separatorStyle =UITableViewCellEditingStyleNone; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil]; //设置做边距 self.inputView.leftView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 8, 0)]; //一直显示 self.inputView.leftViewMode = UITextFieldViewModeAlways; } //点击右下角的send 按钮 - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSLog(@"-------%@",textField.text); [self addMessage:textField.text type:HMMessageModelGatsby]; //自动回复 NSString *autoStr = [self autoReplayWithText:textField.text]; //将自动回复添加成一天聊天信息 [self addMessage:autoStr type:HMMessageModelJobs]; //4. 清空表格 self.inputView.text = @"";//nil return YES; } //自动回复一条聊天信息 - (NSString *)autoReplayWithText:(NSString *)text { //3自动回复 for (int a = 0 ; a < text.length; a++) { NSString *subStr = [text substringWithRange:NSMakeRange(a, 1)]; if (self.autoReplay[subStr]) { return self.autoReplay[subStr]; } } return @"滚蛋吗0"; } - (void)addMessage:(NSString *)text type:(HMMessageModeltype)type { HMMessageModel *msg = [[HMMessageModel alloc]init]; msg.time = @"17:25"; msg.text = text; msg.type = type; HMMessageFrameModel *fm = [[HMMessageFrameModel alloc]init]; fm.message =msg; [self.messagesFrame addObject:fm]; [self.tableView reloadData]; //3. 自动上移 //移动的位置 NSIndexPath *path = [NSIndexPath indexPathForRow:self.messagesFrame.count - 1 inSection:0]; //真正去是位置 atSrcollPosition : 滚到位置 [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } - (void)keyboardDidChangeFrame:(NSNotification *)noti { NSLog(@"--------%@",noti.userInfo); //改变window的背景颜色 self.view.window.backgroundColor = self.tableView.backgroundColor; //最终键盘的frame CGRect frame = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; //键盘实时y CGFloat keyY = frame.origin.y; //屏幕的高度 CGFloat screenH = [[UIScreen mainScreen] bounds].size.height; //动画时间 CGFloat keyDuration = [noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue]; //执行动画 [UIView animateWithDuration:keyDuration animations:^{ self.view.transform = CGAffineTransformMakeTranslation(0, keyY - screenH); }]; } //当tableview 滚动的时候 结束编辑事件 (退出键盘) - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [self.view endEditing:YES]; } //-(NSArray *)messages //{ // if (_messages == nil) { // _messages = [HMMessageModel messages]; // } // return _messages; //} - (NSArray *)messagesFrame { if (_messagesFrame == nil) { _messagesFrame = [HMMessageFrameModel messageFrame]; } return _messagesFrame; } //懒加载自动回复文件 - (NSDictionary *)autoReplay { if (_autoReplay == nil) { _autoReplay = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"autoReplay.plist" ofType:nil]]; } return _autoReplay; } //隐藏状态栏 - (BOOL)prefersStatusBarHidden { return YES; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.messagesFrame.count; } - (UITableViewCell * )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // static NSString *ID [email protected]"cell"; // // HMMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; // // if (cell ==nil) { // cell = [[HMMessageCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; // // } HMMessageCell *cell = [HMMessageCell messageCellWithTableView:tableView]; // cell.messageModel =self.messages[indexPath.row]; HMMessageFrameModel *model = self.messagesFrame[indexPath.row]; cell.frameModel =model; return cell; } #pragma mark - 代理方法 /** 计算单元格行高 */ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { /** 计算行高的方法,会在加载表格数据时,有多少行计算多少次 contentSize 问题:此方法执行的时候,cell还没有被实例化! 但是:行高计算是在实例化cell时,通过设置status属性,计算的=>有了status模型,就可以知道行高! 问题:如何在cell实例化之前,获得行高? 解决方法:通过status可以计算得到行高!=》再建立一个模型,专门计算所有控件的位置 */ // HMMessageFrameModel *messageFrame1 = [[HMMessageFrameModel alloc] init]; // messageFrame1.message =self.messagesFrame[indexPath.row]; // return messageFrame1.cellH; HMMessageFrameModel *messageFrame1 = self.messagesFrame[indexPath.row]; return messageFrame1.cellH; //return 200; } @end
时间: 2024-10-11 04:33:50