LWTViewController.h
#import <UIKit/UIKit.h> @interface LWTViewController : UIViewController @end
LWTViewController.m
1 // 2 // LWTViewController.m 3 // 代码自定义cell练习-- QQ聊天 4 // 5 // Created by apple on 14-5-30. 6 // Copyright (c) 2014年 lwt. All rights reserved. 7 // 8 9 #import "LWTViewController.h" 10 #import "LWTMessageModel.h" 11 #import "LWTMessageCell.h" 12 #import "LWTMessageFrameModel.h" 13 14 @interface LWTViewController () <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate> 15 16 // 定义接收messageFrame模型数组 17 @property (nonatomic, strong) NSMutableArray *messages; 18 // tableView 19 @property (weak, nonatomic) IBOutlet UITableView *tableView; 20 // textField 21 @property (weak, nonatomic) IBOutlet UITextField *textField; 22 // 存放所有的自动回复数据 23 @property (nonatomic, strong) NSDictionary *autoReplays; 24 25 @end 26 27 @implementation LWTViewController 28 29 #pragma mark - 懒加载 30 - (NSMutableArray *)messages 31 { 32 if (nil == _messages) { 33 NSString *path = [[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil]; 34 NSArray *messagesArray = [NSArray arrayWithContentsOfFile:path]; 35 36 NSMutableArray *models = [NSMutableArray arrayWithCapacity:messagesArray.count]; 37 38 for (NSDictionary *dict in messagesArray) { 39 // 获取上一次的数据模型 40 LWTMessageFrameModel *lastMessageFrame = [models lastObject]; 41 LWTMessageModel *lastMessage = lastMessageFrame.message; 42 43 LWTMessageModel *message = [LWTMessageModel messageWithDict:dict]; 44 45 // 设置是否需要隐藏时间 46 message.hiddenTime = [lastMessage.time isEqualToString:message.time]; 47 48 // 根据message创建frame模型 49 LWTMessageFrameModel *msgFrame = [[LWTMessageFrameModel alloc] init]; 50 msgFrame.message = message; 51 52 // 将frame模型保存到数组中 53 [models addObject:msgFrame]; 54 } 55 _messages = [models mutableCopy]; 56 } 57 58 return _messages; 59 } 60 61 - (NSDictionary *)autoReplays 62 { 63 if (!_autoReplays) { 64 NSString *path = [[NSBundle mainBundle] pathForResource:@"autoReplay.plist" ofType:nil]; 65 _autoReplays = [NSDictionary dictionaryWithContentsOfFile:path]; 66 } 67 return _autoReplays; 68 } 69 70 - (void)viewDidLoad 71 { 72 [super viewDidLoad]; 73 // Do any additional setup after loading the view, typically from a nib. 74 75 // 设置隐藏垂直的滚动条 76 self.tableView.showsVerticalScrollIndicator = NO; 77 // 设置tableview的背景颜色 78 self.tableView.backgroundColor = [UIColor colorWithRed:224 / 255.f green:224 / 255.f blue:224 / 255.f alpha:1]; 79 // 设置cell不可以被选中 80 self.tableView.allowsSelection = NO; 81 // 设置隐藏分割线 82 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 83 84 // 创建通知中心 85 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 86 87 // 注册键盘监听器 88 [center addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; 89 90 // 给文本输入框添加左边的视图 91 UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 44)]; 92 self.textField.leftView = leftView; 93 // 设置左边视图的显示模式 94 self.textField.leftViewMode = UITextFieldViewModeAlways; 95 96 // 监听键盘send按钮的点击 97 self.textField.delegate = self; 98 99 } 100 101 #pragma mark - 键盘通知方法 102 103 - (void) keyboardWillChangeFrame : (NSNotification *)notification 104 { 105 // NSLog(@"%@",notification); // 获取通知内容 106 /** 107 * 108 userInfo = { 109 UIKeyboardAnimationCurveUserInfoKey = 7; // 键盘弹出的节奏 110 UIKeyboardAnimationDurationUserInfoKey = "0.25"; // 键盘弹出执行动画的时间 111 UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}"; 112 UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}"; 113 UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}"; 114 UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}"; 115 UIKeyboardFrameChangedByUserInteraction = 0; 116 UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}"; // 键盘弹出时候的frame 117 118 UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}"; // 键盘隐藏时候的frame 119 } 120 */ 121 122 123 // 获取字典 124 NSDictionary *dict = notification.userInfo; 125 126 // 获取键盘的frame,并将NSValue对象转成CGRect 127 CGRect keyBoardFrame = [dict[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 128 // 获取键盘的Y值 129 CGFloat keyBoardY = keyBoardFrame.origin.y; 130 // 获取点击键盘时,self.view移动的y值 131 CGFloat translationY = keyBoardY - self.view.bounds.size.height; 132 // 动画持续时间,并将NSNubmer对象转成double 133 CGFloat duration = [dict[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 134 135 // 执行动画 136 [UIView animateWithDuration:duration delay:0.0 options:7 << 16 animations:^{ 137 // self.view 上下平移 138 self.view.transform = CGAffineTransformMakeTranslation(0, translationY); 139 140 } completion:^(BOOL finished) { 141 }]; 142 143 } 144 145 #pragma mark - UITableViewDataSource 146 - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 147 { 148 return self.messages.count; 149 } 150 151 - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 152 { 153 // 1.创建cell 154 LWTMessageCell *cell = [LWTMessageCell cellWithTableView:tableView]; 155 // 2.设置数据 156 LWTMessageFrameModel *msgFrame = self.messages[indexPath.row]; 157 // 3.返回cell 158 cell.messageFrame = msgFrame; 159 return cell; 160 } 161 162 - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 163 { 164 LWTMessageFrameModel *msgFrame = self.messages[indexPath.row]; 165 return msgFrame.cellHeight; 166 } 167 168 #pragma mark - UITableViewDelegate 169 170 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 171 { 172 /** 173 * 滚动表格,隐藏键盘 174 */ 175 [self.view endEditing:YES]; 176 } 177 178 #pragma mark - UITextFieldDelegate 179 180 - (BOOL)textFieldShouldReturn:(UITextField *)textField 181 { 182 // 自己的话 183 [self addObjectWithtextField:textField.text andtype:LWTMessageModelTypeMe]; 184 NSString *temp = [self autoReplayWithContent:textField.text]; 185 // 自动回复 186 [self addObjectWithtextField:temp andtype:LWTMessageModelTypeOther]; 187 188 // 刷新表格 189 [self.tableView reloadData]; 190 191 // 让tableveiw滚动到最后一行 192 NSIndexPath *path = [NSIndexPath indexPathForRow:self.messages.count-1 inSection:0]; 193 /* 194 AtIndexPath: 要滚动到哪一行 195 atScrollPosition:滚动到哪一行的什么位置 196 animated:是否需要滚动动画 197 */ 198 [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionBottom animated:YES]; 199 200 // 清空输入框 201 self.textField.text = nil; 202 203 return YES; 204 } 205 // 设置自动回复 206 - (NSString *)autoReplayWithContent:(NSString *)text 207 { 208 NSString *result = nil; 209 210 for (int i = 0; i < text.length; i++) { 211 // 取出用户输入的每一个字 212 NSString *str = [text substringWithRange:NSMakeRange(i, 1)]; 213 result = self.autoReplays[str]; 214 // 找到了自动回复的内容 215 if (nil != result) { 216 break; 217 } 218 } 219 if (nil == result) { 220 result = [NSString stringWithFormat:@"%@短发", text]; 221 } 222 223 return result; 224 } 225 226 - (void)addObjectWithtextField: (NSString *)text andtype: (LWTMessageModelType) type 227 { 228 LWTMessageFrameModel *lastFrame = [self.messages lastObject]; 229 LWTMessageModel *lastMessage = lastFrame.message; 230 231 // 创建LWTMessageModel模型 232 LWTMessageModel *message = [[LWTMessageModel alloc] init]; 233 // 当前时间 234 NSDate *date = [NSDate date]; 235 // 将时间转字符串 236 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 237 formatter.dateFormat = @"HH:mm"; 238 239 message.time = [formatter stringFromDate:date]; 240 message.text = text; 241 message.type = type; 242 message.hiddenTime = [message.time isEqualToString:lastMessage.time]; 243 244 // 根据LWTMessageModel模型创建LWTMessageFrameModel模型 245 LWTMessageFrameModel *messageFrame = [[LWTMessageFrameModel alloc] init]; 246 messageFrame.message = message; 247 248 // 将LWTMessageFrameModel模型添加到self.messages数组中 249 [self.messages addObject:messageFrame]; 250 } 251 252 #pragma mark - 隐藏状态栏 253 - (BOOL)prefersStatusBarHidden 254 { 255 return YES; 256 } 257 258 /** 259 * 取消监听通知 260 */ 261 - (void)dealloc 262 { 263 [[NSNotificationCenter defaultCenter] removeObserver:self]; 264 } 265 266 @end
LWTMessageModel.h
1 // 2 // LWTMessageModel.h 3 // 代码自定义cell练习-- QQ聊天 4 // 5 // Created by apple on 14-5-30. 6 // Copyright (c) 2014年 lwt. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import "LWTGlobal.h" 11 12 typedef enum { 13 LWTMessageModelTypeMe = 0, 14 LWTMessageModelTypeOther 15 } LWTMessageModelType; 16 17 @interface LWTMessageModel : NSObject 18 19 @property (nonatomic, copy) NSString *text; 20 @property (nonatomic, copy) NSString *time; 21 @property (nonatomic, assign) LWTMessageModelType type; 22 23 @property (nonatomic, assign, getter = isHiddenTime) BOOL hiddenTime; 24 25 LWTInitH(message) 26 27 @end
LWTMessageModel.m
// // LWTMessageModel.m // 代码自定义cell练习-- QQ聊天 // // Created by apple on 14-5-30. // Copyright (c) 2014年 lwt. All rights reserved. // #import "LWTMessageModel.h" @implementation LWTMessageModel LWTInitM(message) @end
LWTMessageFrameModel.h
// // LWTMessageFrameModel.h // 代码自定义cell练习-- QQ聊天 // // Created by apple on 14-5-30. // Copyright (c) 2014年 lwt. All rights reserved. // #import <Foundation/Foundation.h> @class LWTMessageModel; #define KTextFont [UIFont systemFontOfSize:15] #define KEdgeInsetsWidth 15 @interface LWTMessageFrameModel : NSObject @property (nonatomic, assign, readonly) CGRect timeFrame; @property (nonatomic, assign, readonly) CGRect textFrame; @property (nonatomic, assign, readonly) CGRect iconFrame; @property (nonatomic, assign, readonly) CGFloat cellHeight; @property (nonatomic, strong) LWTMessageModel *message; @end
LWTMessageFrameModel.m
1 // 2 // LWTMessageFrameModel.m 3 // 代码自定义cell练习-- QQ聊天 4 // 5 // Created by apple on 14-5-30. 6 // Copyright (c) 2014年 lwt. All rights reserved. 7 // 8 9 #import "LWTMessageFrameModel.h" 10 #import "NSString+Extension.h" 11 #import "LWTMessageModel.h" 12 13 @implementation LWTMessageFrameModel 14 15 - (void)setMessage:(LWTMessageModel *)message 16 { 17 _message = message; 18 19 CGFloat padding = 10.f; 20 CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; 21 if (NO == message.isHiddenTime) { 22 // 时间的frame 23 CGFloat timeW = screenWidth; 24 CGFloat timeH = 30.f; 25 CGFloat timeX = 0.f; 26 CGFloat timeY = 0.f; 27 _timeFrame = CGRectMake(timeX, timeY, timeW, timeH); 28 } 29 30 31 // 头像的frame 32 CGFloat iconW = 30.f; 33 CGFloat iconH = 30.f; 34 CGFloat iconY = CGRectGetMaxY(self.timeFrame) + padding; 35 36 CGFloat iconX = 0.0f; 37 if (LWTMessageModelTypeMe == self.message.type) { 38 iconX = screenWidth - iconW - padding; 39 } else 40 { 41 iconX = padding; 42 } 43 _iconFrame = CGRectMake(iconX, iconY, iconW, iconH); 44 45 // 内容的frame 46 CGFloat textY = iconY; 47 48 CGSize maxSize = CGSizeMake(200, MAXFLOAT); 49 CGSize textSize = [_message.text sizeWithFont:KTextFont andMaxSize:maxSize]; 50 CGFloat textW = textSize.width + KEdgeInsetsWidth * 2; 51 CGFloat textH = textSize.height + KEdgeInsetsWidth * 2; 52 53 CGFloat textX = 0.0f; 54 if (LWTMessageModelTypeMe == self.message.type) { 55 textX = iconX - textW - padding; 56 } else 57 { 58 textX = CGRectGetMaxX(self.iconFrame) + padding; 59 } 60 _textFrame = CGRectMake(textX, textY, textW, textH); 61 62 // 行高 63 CGFloat iconMaxY = CGRectGetMaxY(self.iconFrame); 64 CGFloat textMaxY = CGRectGetMaxY(self.textFrame); 65 66 _cellHeight = ( iconMaxY > textMaxY ) ? iconMaxY : textMaxY; 67 68 } 69 70 @end
LWTMessageCell.h
// // LWTMessageCell.h // 代码自定义cell练习-- QQ聊天 // // Created by apple on 14-5-30. // Copyright (c) 2014年 lwt. All rights reserved. // #import <UIKit/UIKit.h> @class LWTMessageFrameModel; @interface LWTMessageCell : UITableViewCell + (instancetype) cellWithTableView : (UITableView *)tableView; @property (nonatomic, strong) LWTMessageFrameModel *messageFrame; @end
LWTMessageCell.m
1 // 2 // LWTMessageCell.m 3 // 代码自定义cell练习-- QQ聊天 4 // 5 // Created by apple on 14-5-30. 6 // Copyright (c) 2014年 lwt. All rights reserved. 7 // 8 9 #import "LWTMessageCell.h" 10 #import "LWTMessageFrameModel.h" 11 #import "LWTMessageModel.h" 12 #import "UIImage+Extension.h" 13 14 @interface LWTMessageCell () 15 /** 16 * 时间 17 */ 18 @property (nonatomic, weak) UILabel *timeLabel; 19 /** 20 * 内容 21 */ 22 @property (nonatomic, weak) UIButton *contentButton; 23 /** 24 * 头像 25 */ 26 @property (nonatomic, weak) UIImageView *iconView; 27 28 @end 29 30 @implementation LWTMessageCell 31 32 +(instancetype)cellWithTableView:(UITableView *)tableView 33 { 34 static NSString *identifier = @"message"; 35 LWTMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; 36 if (nil == cell) { 37 cell = [[LWTMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; 38 } 39 return cell; 40 } 41 #warning 内容添加背景 42 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 43 { 44 self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 45 if (self) { 46 // 添加将来有可能用到的子控件 47 // 时间 48 UILabel *timeLabel = [[UILabel alloc] init]; 49 [self.contentView addSubview:timeLabel]; 50 timeLabel.textAlignment = NSTextAlignmentCenter; 51 timeLabel.font = [UIFont systemFontOfSize:13.f]; 52 timeLabel.textColor = [UIColor grayColor]; 53 self.timeLabel = timeLabel; 54 55 // 内容 56 UIButton *contentButton = [[UIButton alloc] init]; 57 [self.contentView addSubview:contentButton]; 58 [contentButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 59 contentButton.titleLabel.font = KTextFont; 60 // 设置自动换行 61 contentButton.titleLabel.numberOfLines = 0; 62 // 设置按钮的内边距 63 contentButton.contentEdgeInsets = UIEdgeInsetsMake(KEdgeInsetsWidth, KEdgeInsetsWidth, KEdgeInsetsWidth, KEdgeInsetsWidth); 64 self.contentButton = contentButton; 65 66 // 头像 67 UIImageView *iconView = [[UIImageView alloc] init]; 68 [self.contentView addSubview:iconView]; 69 self.iconView =iconView; 70 71 // 清空cell的背景颜色 72 self.backgroundColor = [UIColor clearColor]; 73 } 74 return self; 75 } 76 77 // 重写message的setter 78 - (void)setMessageFrame:(LWTMessageFrameModel *)messageFrame 79 { 80 _messageFrame = messageFrame; 81 // 获取数据模型 82 LWTMessageModel *message = messageFrame.message; 83 84 // 向子控件赋值和frame 85 86 // 时间 87 self.timeLabel.text = message.time; 88 self.timeLabel.frame = messageFrame.timeFrame; 89 90 // 头像 91 if (LWTMessageModelTypeMe == message.type) { 92 self.iconView.image = [UIImage imageNamed:@"me"]; 93 } else 94 { 95 self.iconView.image = [UIImage imageNamed:@"other"]; 96 } 97 self.iconView.frame = messageFrame.iconFrame; 98 99 // 内容 100 [self.contentButton setTitle:message.text forState:UIControlStateNormal]; 101 self.contentButton.frame = messageFrame.textFrame; 102 103 UIImage *nor_img = nil; 104 105 if (LWTMessageModelTypeMe == message.type) { 106 107 nor_img = [UIImage resizableImageWithImageName:@"chat_send_nor"]; 108 109 } else 110 { 111 nor_img = [UIImage resizableImageWithImageName:@"chat_recive_nor"]; 112 113 } 114 [self.contentButton setBackgroundImage:nor_img forState:UIControlStateNormal]; 115 116 } 117 @end
NSString+Extension.h
// // NSString+Extension.h // 代码自定义cell练习-- QQ聊天 // // Created by apple on 14-5-30. // Copyright (c) 2014年 lwt. All rights reserved. // #import <Foundation/Foundation.h> @interface NSString (Extension) - (CGSize)sizeWithFont:(UIFont *)font andMaxSize: (CGSize)maxSize; @end
NSString+Extension.m
// // NSString+Extension.m // 代码自定义cell练习-- QQ聊天 // // Created by apple on 14-5-30. // Copyright (c) 2014年 lwt. All rights reserved. // #import "NSString+Extension.h" @implementation NSString (Extension) - (CGSize)sizeWithFont:(UIFont *)font andMaxSize:(CGSize)maxSize { NSDictionary *dict = @{NSFontAttributeName : font}; CGSize size = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size; return size; } @end
UIImage+Extension.h
// // UIImage+Extension.h // 代码自定义cell练习-- QQ聊天 // // Created by apple on 14-6-1. // Copyright (c) 2014年 lwt. All rights reserved. // #import <UIKit/UIKit.h> @interface UIImage (Extension) + (UIImage *)resizableImageWithImageName : (NSString *) imageName; @end
UIImage+Extension.m
// // UIImage+Extension.m // 代码自定义cell练习-- QQ聊天 // // Created by apple on 14-6-1. // Copyright (c) 2014年 lwt. All rights reserved. // #import "UIImage+Extension.h" @implementation UIImage (Extension) + (UIImage *)resizableImageWithImageName:(NSString *)imageName { UIImage *norImg = [UIImage imageNamed:imageName]; CGFloat imgWidth = norImg.size.width * 0.5; CGFloat imageHeight = norImg.size.height * 0.5; UIImage *newImg = [norImg resizableImageWithCapInsets:UIEdgeInsetsMake(imageHeight - 1, imgWidth - 1, imageHeight, imgWidth) resizingMode:UIImageResizingModeStretch]; return newImg; } @end
LWTGlobal.h
// // LWTGlobal.h // tableView练习--英雄联盟英雄介绍 // // Created by apple on 14-5-27. // Copyright (c) 2014年 lwt. All rights reserved. // #ifndef tableView_____________LWTGlobal_h #define tableView_____________LWTGlobal_h #define LWTInitH(name) - (instancetype)initWithDict : (NSDictionary *)dict; + (instancetype)name##WithDict : (NSDictionary *)dict; #define LWTInitM(name) - (instancetype)initWithDict:(NSDictionary *)dict { self = [super init]; if (self) { [self setValuesForKeysWithDictionary:dict]; } return self; } + (instancetype)name##WithDict:(NSDictionary *)dict { return [[self alloc] initWithDict:dict]; } #endif
messages.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <array> <dict> <key>text</key> <string>喂,2B!</string> <key>time</key> <string>前天 10:27</string> <key>type</key> <integer>0</integer> </dict> <dict> <key>text</key> <string>问你个严肃的事</string> <key>time</key> <string>前天 10:28</string> <key>type</key> <integer>0</integer> </dict> <dict> <key>text</key> <string>你妹夫啊,你才2B!说,什么事?</string> <key>time</key> <string>昨天 20:05</string> <key>type</key> <integer>1</integer> </dict> <dict> <key>text</key> <string>你姐夫啊,我就想问下:你是不是我最好的朋友?</string> <key>time</key> <string>昨天 20:07</string> <key>type</key> <integer>0</integer> </dict> <dict> <key>text</key> <string>不借</string> <key>time</key> <string>昨天 20:07</string> <key>type</key> <integer>1</integer> </dict> <dict> <key>text</key> <string>借你妹夫啊,老子又不缺钱。你就回答“是”或者“不是”。</string> <key>time</key> <string>昨天 20:07</string> <key>type</key> <integer>0</integer> </dict> <dict> <key>text</key> <string>是</string> <key>time</key> <string>昨天 20:11</string> <key>type</key> <integer>1</integer> </dict> <dict> <key>text</key> <string>刚才看了部非常感人的电视剧,电视上说狗才是人类最好的朋友,所以我想确认一下</string> <key>time</key> <string>昨天 20:15</string> <key>type</key> <integer>0</integer> </dict> <dict> <key>text</key> <string>你妈B的!!!滚!!!</string> <key>time</key> <string>昨天 20:15</string> <key>type</key> <integer>1</integer> </dict> </array> </plist>
autoReplay.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>爱</key> <string>爱是深深的喜欢</string> <key>喜</key> <string>喜欢是淡淡的爱</string> </dict> </plist>