[iOS基础控件 - 6.9.1] 聊天界面Demo 代码
2014-12-08 21:54
411 查看
框架:
![](http://images.cnitblog.com/blog/648473/201412/082154157906208.png)
所有代码文件:
![](http://images.cnitblog.com/blog/648473/201412/082154171184235.png)
Model:
View:
Controller:
工具类:
![](http://images.cnitblog.com/blog/648473/201412/082154157906208.png)
所有代码文件:
![](http://images.cnitblog.com/blog/648473/201412/082154171184235.png)
Model:
// // Message.h // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // // message信息模型,存储聊天记录 #import <Foundation/Foundation.h> typedef enum { MessageTypeMe = 0, // 我发出的信息 MessageTypeOhter = 1 // 对方发出的信息 } MessageType; @interface Message : NSObject /** 信息 */ @property(nonatomic, copy) NSString *text; /** 发送时间 */ @property(nonatomic, copy) NSString *time; /** 发送方 */ @property(nonatomic, assign) MessageType type; /** 是否隐藏发送时间 */ @property(nonatomic, assign) BOOL hideTime; - (instancetype) initWithDictionary:(NSDictionary *) dictionary; + (instancetype) messageWithDictionary:(NSDictionary *) dictionary; + (instancetype) message; @end
// // Message.m // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // #import "Message.h" @implementation Message - (instancetype) initWithDictionary:(NSDictionary *) dictionary { if (self = [super init]) { [self setValuesForKeysWithDictionary:dictionary]; } return self; } + (instancetype) messageWithDictionary:(NSDictionary *) dictionary { return [[self alloc] initWithDictionary:dictionary]; } + (instancetype) message { return [self messageWithDictionary:nil]; } @end
// // MessageFrame.h // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // // 存储每个cell内子控件的位置尺寸的frame #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import "Message.h" #define MESSAGE_TIME_FONT [UIFont systemFontOfSize:13] #define MESSAGE_TEXT_FONT [UIFont systemFontOfSize:15] #define TEXT_INSET 20 @interface MessageFrame : NSObject /** 发送时间 */ @property(nonatomic, assign, readonly) CGRect timeFrame; /** 头像 */ @property(nonatomic, assign, readonly) CGRect iconFrame; /** 信息 */ @property(nonatomic, assign, readonly) CGRect textFrame; /** 信息model */ @property(nonatomic, strong) Message *message; /** cell的高度 */ @property(nonatomic, assign) CGFloat cellHeight; @end
// // MessageFrame.m // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // #import "MessageFrame.h" #import "NSString+Extension.h" @implementation MessageFrame /** 设置message,计算位置尺寸 */ - (void)setMessage:(Message *)message { _message = message; // 间隙 CGFloat padding = 10; // 1.发送时间 if (NO == message.hideTime) { CGFloat timeWidth = [UIScreen mainScreen].bounds.size.width; CGFloat timeHeight = 40; CGFloat timeX = 0; CGFloat timeY = 0; _timeFrame = CGRectMake(timeX, timeY, timeWidth, timeHeight); } // 2.头像 CGFloat iconWidth = 40; CGFloat iconHeight = 40; // 2.1 根据信息的发送方调整头像位置 CGFloat iconX; if (MessageTypeMe == message.type) { // 我方,放在右边 iconX = [UIScreen mainScreen].bounds.size.width - padding - iconWidth; } else { // 对方,放在左边 iconX = padding; } CGFloat iconY = CGRectGetMaxY(_timeFrame) + padding; _iconFrame = CGRectMake(iconX, iconY, iconWidth, iconHeight); // 3.信息,尺寸可变 CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; // 3.1 设置文本最大尺寸 CGSize textMaxSize = CGSizeMake(screenWidth - iconWidth - padding * 10, MAXFLOAT); // 3.2 计算文本真实尺寸 CGSize textRealSize = [message.text sizeWithFont:MESSAGE_TEXT_FONT maxSize:textMaxSize]; // 3.3 按钮尺寸 CGSize btnSize = CGSizeMake(textRealSize.width + TEXT_INSET*2, textRealSize.height + TEXT_INSET*2); // 3.4 调整信息的位置 CGFloat textX; if (MessageTypeMe == message.type) { // 我方,放在靠右 textX = CGRectGetMinX(_iconFrame) - btnSize.width - padding; } else { // 对方,放在靠左 textX = CGRectGetMaxX(_iconFrame) + padding; } CGFloat textY = iconY; _textFrame = CGRectMake(textX, textY, btnSize.width, btnSize.height); // 4.cell的高度 CGFloat iconMaxY = CGRectGetMaxY(_iconFrame); CGFloat textMaxY = CGRectGetMaxY(_textFrame); _cellHeight = MAX(iconMaxY, textMaxY) + padding; } @end
View:
// // MessageCell.h // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // #import <UIKit/UIKit.h> #define BACKGROUD_COLOR [UIColor colorWithRed:235/255.0 green:235/255.0 blue:235/255.0 alpha:1.0] @class MessageFrame, Message; @interface MessageCell : UITableViewCell /** 持有存储了聊天记录和聊天框位置尺寸的frame */ @property(nonatomic, strong) MessageFrame *messageFrame; /** 传入父控件tableView引用的构造方法 */ + (instancetype) cellWithTableView:(UITableView *) tableView; @end
// // MessageCell.m // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // #import "MessageCell.h" #import "MessageFrame.h" #import "UIImage+Extension.h" @interface MessageCell() // 定义cell内的子控件,用于保存控件,然后进行数据和位置尺寸的计算 /** 发送时间 */ @property(nonatomic, weak) UILabel *timeLabel; /** 头像 */ @property(nonatomic, weak) UIImageView *iconView; /** 信息 */ @property(nonatomic, weak) UIButton *textView; @end @implementation MessageCell - (void)awakeFromNib { // Initialization code } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } #pragma mark - 构造方法 // 自定义构造方法 + (instancetype) cellWithTableView:(UITableView *) tableView { static NSString *ID = @"message"; // 使用缓存池 MessageCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; // 创建一个新的cell if (nil == cell) { cell = [[MessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } return cell; } // 重写构造方法,创建cell中的各个子控件 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; // 设置cell的背景色 self.backgroundColor = BACKGROUD_COLOR; // 1.发送时间 UILabel *timeLabel = [[UILabel alloc] init]; [timeLabel setTextAlignment:NSTextAlignmentCenter]; [timeLabel setFont:MESSAGE_TIME_FONT]; [timeLabel setTextColor:[UIColor grayColor]]; [self.contentView addSubview:timeLabel]; self.timeLabel = timeLabel; // 2.头像 UIImageView *iconView = [[UIImageView alloc] init]; [self.contentView addSubview:iconView]; self.iconView = iconView; // 3.信息 UIButton *textView = [[UIButton alloc] init]; [textView setTitle:@"text" forState:UIControlStateNormal]; [textView.titleLabel setFont:MESSAGE_TEXT_FONT]; // 3.1 如果是浅色背景,记得设置字体颜色,因为按钮的字体颜色默认是白色 [textView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [textView.titleLabel setNumberOfLines:0]; // 设置自动换行 // 3.2 调整文字的内边距 textView.contentEdgeInsets = UIEdgeInsetsMake(TEXT_INSET, TEXT_INSET, TEXT_INSET, TEXT_INSET); [self.contentView addSubview:textView]; self.textView = textView; return self; } #pragma mark - 加载数据 // 加载frame,初始化cell中子控件的数据、位置尺寸 - (void)setMessageFrame:(MessageFrame *) messageFrame { _messageFrame = messageFrame; // 1.发送时间 self.timeLabel.text = messageFrame.message.time; self.timeLabel.frame = messageFrame.timeFrame; // 2.头像 NSString *icon = (messageFrame.message.type == MessageTypeMe)? @"me":@"other"; self.iconView.image = [UIImage imageNamed:icon]; self.iconView.frame = messageFrame.iconFrame; // 3.信息 [self.textView setTitle:messageFrame.message.text forState:UIControlStateNormal]; self.textView.frame = messageFrame.textFrame; // 3.1 设置聊天框 NSString *chatImageNormalName; NSString *chatImageHighlightedName; if (MessageTypeMe == messageFrame.message.type) { chatImageNormalName = @"chat_send_nor"; chatImageHighlightedName = @"chat_send_press_pic"; } else { chatImageNormalName = @"chat_receive_nor"; chatImageHighlightedName = @"chat_receive_press_pic"; } UIImage *chatImageNormal = [UIImage resizableImage:chatImageNormalName]; UIImage *chatImageHighlighted = [UIImage resizableImage:chatImageHighlightedName]; [self.textView setBackgroundImage:chatImageNormal forState:UIControlStateNormal]; [self.textView setBackgroundImage:chatImageHighlighted forState:UIControlStateHighlighted]; } @end
Controller:
// // ViewController.m // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // #import "ViewController.h" #import "Message.h" #import "MessageCell.h" #import "MessageFrame.h" @interface ViewController () <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate> /** 聊天区tableView */ @property (weak, nonatomic) IBOutlet UITableView *tableView; /** 信息记录数据 */ @property(nonatomic, strong) NSMutableArray *messages; /** 信息输入框 */ @property (weak, nonatomic) IBOutlet UITextField *inputView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 设置dataSource self.tableView.dataSource = self; // 设置tableView的delegate self.tableView.delegate = self; // 设置tableView背景色,当键盘呼出隐藏的时候,避免默认的黑色背景出现太突兀 self.tableView.backgroundColor = BACKGROUD_COLOR; // 设置聊天区TableView // 不使用分割线 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 禁止选中cell [self.tableView setAllowsSelection:NO]; // 设置虚拟键盘监听器 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; // 设置TextField文字左间距 self.inputView.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)]; self.inputView.leftViewMode = UITextFieldViewModeAlways; // 设置信息输入框的代理 self.inputView.delegate = self; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (BOOL)prefersStatusBarHidden { return YES; } #pragma mark - 数据加载 /** 延迟加载plist文件数据 */ - (NSMutableArray *)messages { if (nil == _messages) { NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil]]; NSMutableArray *mdictArray = [NSMutableArray array]; for (NSDictionary *dict in dictArray) { Message *message = [Message messageWithDictionary:dict]; // 判断是否发送时间与上一条信息的发送时间相同,若是则不用显示了 MessageFrame *lastMessageFrame = [mdictArray lastObject]; if (lastMessageFrame && [message.time isEqualToString:lastMessageFrame.message.time]) { message.hideTime = YES; } MessageFrame *messageFrame = [[MessageFrame alloc] init]; messageFrame.message = message; [mdictArray addObject:messageFrame]; } _messages = mdictArray; } return _messages; } #pragma mark - dataSource方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.messages.count; } - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { MessageCell *cell = [MessageCell cellWithTableView:self.tableView]; cell.messageFrame = self.messages[indexPath.row]; return cell; } #pragma mark - tableView代理方法 /** 动态设置每个cell的高度 */ - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { MessageFrame *messageFrame = self.messages[indexPath.row]; return messageFrame.cellHeight; } #pragma mark - scrollView 代理方法 /** 点击拖曳聊天区的时候,缩回键盘 */ - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // 1.缩回键盘 [self.view endEditing:YES]; } #pragma mark - 监听事件 - (void) keyboardWillChangeFrame:(NSNotification *) note { // 1.取得弹出后的键盘frame CGRect keyboardFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; // 2.键盘弹出的耗时时间 CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue]; // 3.键盘变化时,view的位移,包括了上移/恢复下移 CGFloat transformY = keyboardFrame.origin.y - self.view.frame.size.height; [UIView animateWithDuration:duration animations:^{ self.view.transform = CGAffineTransformMakeTranslation(0, transformY); }]; } #pragma mark - TextField 代理方法 /** 回车响应事件 */ - (BOOL)textFieldShouldReturn:(UITextField *)textField { // 我方发出信息 [self sendMessageWithContent:textField.text andType:MessageTypeMe]; // 自动回复 [self sendMessageWithContent:[NSString stringWithFormat:@"%@\n%@", textField.text, @"你妹!!!"] andType:MessageTypeOhter]; // 消除消息框内容 self.inputView.text = nil; [self.tableView reloadData]; // 滚动到最新的消息 NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:self.messages.count - 1 inSection:0]; [self.tableView scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; return YES; // 返回值意义不明 } // 发送消息 - (void) sendMessageWithContent:(NSString *) text andType:(MessageType) type { // 获取当前时间 NSDate *date = [NSDate date]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy-MMM-dd hh:mm:ss"; NSString *dateStr = [formatter stringFromDate:date]; // 我方发出信息 NSDictionary *dict = @{@"text":text, @"time":dateStr, @"type":[NSString stringWithFormat:@"%d", type]}; Message *message = [[Message alloc] init]; [message setValuesForKeysWithDictionary:dict]; MessageFrame *messageFrame = [[MessageFrame alloc] init]; messageFrame.message = message; [self.messages addObject:messageFrame]; } @end
工具类:
// // NSString+Extension.h // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // // NSString扩展类 #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface NSString (Extension) /** 测量文本的尺寸 */ - (CGSize) sizeWithFont:(UIFont *)font maxSize:(CGSize) maxSize; @end
// // NSString+Extension.m // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // #import "NSString+Extension.h" @implementation NSString (Extension) /** 测量文本的尺寸 */ - (CGSize)sizeWithFont:(UIFont *)font maxSize:(CGSize)maxSize { NSDictionary *attrs = @{NSFontAttributeName: font}; CGSize size = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size; return size; } @end
// // UIImage+Extension.h // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // // NSImage 类的扩展 #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface UIImage (Extension) + (UIImage *) resizableImage:(NSString *) imageName; @end
// // UIImage+Extension.m // QQChatDemo // // Created by hellovoidworld on 14/12/8. // Copyright (c) 2014年 hellovoidworld. All rights reserved. // #import "UIImage+Extension.h" @implementation UIImage (Extension) + (UIImage *) resizableImage:(NSString *) imageName { UIImage *image = [UIImage imageNamed:imageName]; // 取图片中部的1 x 1进行拉伸 UIEdgeInsets insets = UIEdgeInsetsMake(image.size.height/2, image.size.width/2, image.size.height/2 + 1, image.size.width/2 + 1); return [image resizableImageWithCapInsets:insets]; } @end
相关文章推荐
- 【iOS基础控件 - 11】【Demo】模仿qq ,微信 UI 聊天界面
- [iOS基础控件 - 6.9] 聊天界面Demo
- [iOS基础控件 - 3.1] QQ登陆界面
- [iOS基础控件 - 6.7] 微博展示 使用代码自定义TableCell(动态尺寸)
- 【iOS基础控件 - 8 】【demo】 展示团购数据 UITableViewCell <代理,xib封装view>
- IOS开发之纯代码界面--基本控件使用篇
- IOS开发之纯代码界面----基本控件使用篇2
- [iOS基础控件 - 5.2] 查看大图、缩放图片代码(UIScrollView制作)
- 看完以上的chrome所用到的基础控件之后,如果想改chrome 的界面,需要看那一片代码呢
- 【iOS基础控件- 5 】【demo】 超级猜图 <UIButton + UIImageView>
- iOS开发UI基础—24使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- [iOS基础控件 - 5.4] 广告分页代码(UIScrollView制作)
- 【iOS基础控件 - 2 】 用代码创建控件,不用storyboard
- [iOS基础控件 - 6.6.1] 展示团购数据代码[iOS基础控件 - 6.7] 微博展示 使用代码自定义TableCell(动态尺寸)
- 【iOS基础控件 - 13】【Demo 】QQ好友列表TableView
- IOS开发之纯代码界面--基本控件使用篇 ┊
- [iOS基础控件 - 6.6.1] 展示团购数据代码
- [iOS基础控件 - 6.10.1] PickerView 餐点搭配Demo
- [iOS基础控件 - 6.10.2] PickerView 自定义row内容 国家选择Demo
- IOS开发之纯代码界面----基本控件使用篇3