当前位置:   article > 正文

[iOS基础控件 - 6.9.1] 聊天界面Demo 代码

oc 聊天框 demo
框架:
Image(108)
 
所有代码文件
Image(118)
 
Model:
 1 //
 2 //  Message.h
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 // message信息模型,存储聊天记录
 9 
10 #import <Foundation/Foundation.h>
11 
12 typedef enum {
13     MessageTypeMe = 0, // 我发出的信息
14     MessageTypeOhter = 1 // 对方发出的信息
15 } MessageType;
16 
17 @interface Message : NSObject
18 
19 /** 信息 */
20 @property(nonatomic, copy) NSString *text;
21 
22 /** 发送时间 */
23 @property(nonatomic, copy) NSString *time;
24 
25 /** 发送方 */
26 @property(nonatomic, assign) MessageType type;
27 
28 /** 是否隐藏发送时间 */
29 @property(nonatomic, assign) BOOL hideTime;
30 
31 - (instancetype) initWithDictionary:(NSDictionary *) dictionary;
32 + (instancetype) messageWithDictionary:(NSDictionary *) dictionary;
33 + (instancetype) message;
34 
35 @end
 
 1 //
 2 //  Message.m
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "Message.h"
10 
11 @implementation Message
12 
13 - (instancetype) initWithDictionary:(NSDictionary *) dictionary {
14     if (self = [super init]) {
15         [self setValuesForKeysWithDictionary:dictionary];
16     }
17    
18     return self;
19 }
20 
21 + (instancetype) messageWithDictionary:(NSDictionary *) dictionary {
22     return [[self alloc] initWithDictionary:dictionary];
23 }
24 
25 + (instancetype) message {
26     return [self messageWithDictionary:nil];
27 }
28 
29 @end
 
 1 //
 2 //  MessageFrame.h
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 // 存储每个cell内子控件的位置尺寸的frame
 9 
10 #import <Foundation/Foundation.h>
11 #import <UIKit/UIKit.h>
12 #import "Message.h"
13 
14 #define MESSAGE_TIME_FONT [UIFont systemFontOfSize:13]
15 #define MESSAGE_TEXT_FONT [UIFont systemFontOfSize:15]
16 #define TEXT_INSET 20
17 
18 @interface MessageFrame : NSObject
19 
20 /** 发送时间  */
21 @property(nonatomic, assign, readonly) CGRect timeFrame;
22 
23 /** 头像 */
24 @property(nonatomic, assign, readonly) CGRect iconFrame;
25 
26 /** 信息 */
27 @property(nonatomic, assign, readonly) CGRect textFrame;
28 
29 /** 信息model */
30 @property(nonatomic, strong) Message *message;
31 
32 /** cell的高度 */
33 @property(nonatomic, assign) CGFloat cellHeight;
34 
35 
36 @end
 
 1 //
 2 //  MessageFrame.m
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "MessageFrame.h"
10 #import "NSString+Extension.h"
11 
12 @implementation MessageFrame
13 
14 /** 设置message,计算位置尺寸 */
15 - (void)setMessage:(Message *)message {
16     _message = message;
17 
18     // 间隙
19     CGFloat padding = 10;
20    
21     // 1.发送时间
22     if (NO == message.hideTime) {
23         CGFloat timeWidth = [UIScreen mainScreen].bounds.size.width;
24         CGFloat timeHeight = 40;
25         CGFloat timeX = 0;
26         CGFloat timeY = 0;
27         _timeFrame = CGRectMake(timeX, timeY, timeWidth, timeHeight);
28     }
29    
30     // 2.头像
31     CGFloat iconWidth = 40;
32     CGFloat iconHeight = 40;
33    
34     // 2.1 根据信息的发送方调整头像位置
35     CGFloat iconX;
36     if (MessageTypeMe == message.type) {
37         // 我方,放在右边
38         iconX = [UIScreen mainScreen].bounds.size.width - padding - iconWidth;
39     } else {
40         // 对方,放在左边
41         iconX = padding;
42     }
43    
44     CGFloat iconY = CGRectGetMaxY(_timeFrame) + padding;
45     _iconFrame = CGRectMake(iconX, iconY, iconWidth, iconHeight);
46    
47     // 3.信息,尺寸可变
48     CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
49     // 3.1 设置文本最大尺寸
50     CGSize textMaxSize = CGSizeMake(screenWidth - iconWidth - padding * 10, MAXFLOAT);
51     // 3.2 计算文本真实尺寸
52     CGSize textRealSize = [message.text sizeWithFont:MESSAGE_TEXT_FONT maxSize:textMaxSize];
53    
54     // 3.3 按钮尺寸
55     CGSize btnSize = CGSizeMake(textRealSize.width + TEXT_INSET*2, textRealSize.height + TEXT_INSET*2);
56 
57     // 3.4 调整信息的位置
58     CGFloat textX;
59     if (MessageTypeMe == message.type) {
60         // 我方,放在靠右
61         textX = CGRectGetMinX(_iconFrame) - btnSize.width - padding;
62     } else {
63         // 对方,放在靠左
64         textX = CGRectGetMaxX(_iconFrame) + padding;
65     }
66    
67     CGFloat textY = iconY;
68     _textFrame = CGRectMake(textX, textY, btnSize.width, btnSize.height);
69    
70     // 4.cell的高度
71     CGFloat iconMaxY = CGRectGetMaxY(_iconFrame);
72     CGFloat textMaxY = CGRectGetMaxY(_textFrame);
73     _cellHeight = MAX(iconMaxY, textMaxY) + padding;
74 }
75 
76 
77 @end
 
View:
 1 //
 2 //  MessageCell.h
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 #define BACKGROUD_COLOR [UIColor colorWithRed:235/255.0 green:235/255.0 blue:235/255.0 alpha:1.0]
12 
13 @class MessageFrame, Message;
14 
15 @interface MessageCell : UITableViewCell
16 
17 /** 持有存储了聊天记录和聊天框位置尺寸的frame */
18 @property(nonatomic, strong) MessageFrame *messageFrame;
19 
20 /** 传入父控件tableView引用的构造方法 */
21 + (instancetype) cellWithTableView:(UITableView *) tableView;
22 
23 @end
 
  1 //
  2 //  MessageCell.m
  3 //  QQChatDemo
  4 //
  5 //  Created by hellovoidworld on 14/12/8.
  6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
  7 //
  8 
  9 #import "MessageCell.h"
 10 #import "MessageFrame.h"
 11 #import "UIImage+Extension.h"
 12 
 13 @interface MessageCell()
 14 
 15 // 定义cell内的子控件,用于保存控件,然后进行数据和位置尺寸的计算
 16 /** 发送时间 */
 17 @property(nonatomic, weak) UILabel *timeLabel;
 18 
 19 /** 头像 */
 20 @property(nonatomic, weak) UIImageView *iconView;
 21 
 22 /** 信息 */
 23 @property(nonatomic, weak) UIButton *textView;
 24 
 25 @end
 26 
 27 @implementation MessageCell
 28 
 29 - (void)awakeFromNib {
 30     // Initialization code
 31 }
 32 
 33 - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
 34     [super setSelected:selected animated:animated];
 35 
 36     // Configure the view for the selected state
 37 }
 38 
 39 #pragma mark - 构造方法
 40 // 自定义构造方法
 41 + (instancetype) cellWithTableView:(UITableView *) tableView {
 42     static NSString *ID = @"message";
 43    
 44     // 使用缓存池
 45     MessageCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
 46    
 47     // 创建一个新的cell
 48     if (nil == cell) {
 49         cell = [[MessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
 50     }
 51    
 52     return cell;
 53 }
 54 
 55 // 重写构造方法,创建cell中的各个子控件
 56 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
 57     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
 58    
 59     // 设置cell的背景色
 60     self.backgroundColor = BACKGROUD_COLOR;
 61    
 62     // 1.发送时间
 63     UILabel *timeLabel = [[UILabel alloc] init];
 64     [timeLabel setTextAlignment:NSTextAlignmentCenter];
 65     [timeLabel setFont:MESSAGE_TIME_FONT];
 66     [timeLabel setTextColor:[UIColor grayColor]];
 67     [self.contentView addSubview:timeLabel];
 68     self.timeLabel = timeLabel;
 69    
 70     // 2.头像
 71     UIImageView *iconView = [[UIImageView alloc] init];
 72     [self.contentView addSubview:iconView];
 73     self.iconView = iconView;
 74    
 75     // 3.信息
 76     UIButton *textView = [[UIButton alloc] init];
 77     [textView setTitle:@"text" forState:UIControlStateNormal];
 78     [textView.titleLabel setFont:MESSAGE_TEXT_FONT];
 79    
 80     // 3.1 如果是浅色背景,记得设置字体颜色,因为按钮的字体颜色默认是白色
 81     [textView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
 82     [textView.titleLabel setNumberOfLines:0]; // 设置自动换行
 83    
 84     // 3.2 调整文字的内边距
 85     textView.contentEdgeInsets = UIEdgeInsetsMake(TEXT_INSET, TEXT_INSET, TEXT_INSET, TEXT_INSET);
 86    
 87     [self.contentView addSubview:textView];
 88     self.textView = textView;
 89    
 90     return self;
 91 }
 92 
 93 #pragma mark - 加载数据
 94 // 加载frame,初始化cell中子控件的数据、位置尺寸
 95 - (void)setMessageFrame:(MessageFrame *) messageFrame {
 96     _messageFrame = messageFrame;
 97    
 98     // 1.发送时间
 99     self.timeLabel.text = messageFrame.message.time;
100     self.timeLabel.frame = messageFrame.timeFrame;
101    
102     // 2.头像
103     NSString *icon = (messageFrame.message.type == MessageTypeMe)? @"me":@"other";
104     self.iconView.image = [UIImage imageNamed:icon];
105     self.iconView.frame = messageFrame.iconFrame;
106    
107     // 3.信息
108     [self.textView setTitle:messageFrame.message.text forState:UIControlStateNormal];
109     self.textView.frame = messageFrame.textFrame;
110    
111     // 3.1 设置聊天框
112     NSString *chatImageNormalName;
113     NSString *chatImageHighlightedName;
114     if (MessageTypeMe == messageFrame.message.type) {
115         chatImageNormalName = @"chat_send_nor";
116         chatImageHighlightedName = @"chat_send_press_pic";
117     } else {
118         chatImageNormalName = @"chat_receive_nor";
119         chatImageHighlightedName = @"chat_receive_press_pic";
120     }
121    
122     UIImage *chatImageNormal = [UIImage resizableImage:chatImageNormalName];
123     UIImage *chatImageHighlighted = [UIImage resizableImage:chatImageHighlightedName];
124     [self.textView setBackgroundImage:chatImageNormal forState:UIControlStateNormal];
125     [self.textView setBackgroundImage:chatImageHighlighted forState:UIControlStateHighlighted];
126 }
127 
128 
129 @end
 
Controller:
  1 //
  2 //  ViewController.m
  3 //  QQChatDemo
  4 //
  5 //  Created by hellovoidworld on 14/12/8.
  6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
  7 //
  8 
  9 #import "ViewController.h"
 10 #import "Message.h"
 11 #import "MessageCell.h"
 12 #import "MessageFrame.h"
 13 
 14 @interface ViewController () <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate>
 15 
 16 /** 聊天区tableView */
 17 @property (weak, nonatomic) IBOutlet UITableView *tableView;
 18 
 19 /** 信息记录数据 */
 20 @property(nonatomic, strong) NSMutableArray *messages;
 21 
 22 /** 信息输入框 */
 23 @property (weak, nonatomic) IBOutlet UITextField *inputView;
 24 
 25 @end
 26 
 27 @implementation ViewController
 28 
 29 - (void)viewDidLoad {
 30     [super viewDidLoad];
 31     // Do any additional setup after loading the view, typically from a nib.
 32    
 33     // 设置dataSource
 34     self.tableView.dataSource = self;
 35    
 36     // 设置tableView的delegate
 37     self.tableView.delegate = self;
 38    
 39     // 设置tableView背景色,当键盘呼出隐藏的时候,避免默认的黑色背景出现太突兀
 40     self.tableView.backgroundColor = BACKGROUD_COLOR;
 41    
 42     // 设置聊天区TableView
 43     // 不使用分割线
 44     self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
 45     // 禁止选中cell
 46     [self.tableView setAllowsSelection:NO];
 47    
 48     // 设置虚拟键盘监听器
 49     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
 50    
 51     // 设置TextField文字左间距
 52     self.inputView.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)];
 53     self.inputView.leftViewMode = UITextFieldViewModeAlways;
 54    
 55     // 设置信息输入框的代理
 56     self.inputView.delegate = self;
 57 }
 58 
 59 - (void)didReceiveMemoryWarning {
 60     [super didReceiveMemoryWarning];
 61     // Dispose of any resources that can be recreated.
 62 }
 63 
 64 - (BOOL)prefersStatusBarHidden {
 65     return YES;
 66 }
 67 
 68 #pragma mark - 数据加载
 69 /** 延迟加载plist文件数据 */
 70 - (NSMutableArray *)messages {
 71     if (nil == _messages) {
 72         NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil]];
 73        
 74         NSMutableArray *mdictArray = [NSMutableArray array];
 75         for (NSDictionary *dict in dictArray) {
 76             Message *message = [Message messageWithDictionary:dict];
 77            
 78             // 判断是否发送时间与上一条信息的发送时间相同,若是则不用显示了
 79             MessageFrame *lastMessageFrame = [mdictArray lastObject];
 80             if (lastMessageFrame && [message.time isEqualToString:lastMessageFrame.message.time]) {
 81                 message.hideTime = YES;
 82             }
 83            
 84             MessageFrame *messageFrame = [[MessageFrame alloc] init];
 85             messageFrame.message = message;
 86             [mdictArray addObject:messageFrame];
 87         }
 88        
 89         _messages = mdictArray;
 90     }
 91    
 92     return _messages;
 93 }
 94 
 95 #pragma mark - dataSource方法
 96 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 97     return  self.messages.count;
 98 }
 99 
100 - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
101     MessageCell *cell = [MessageCell cellWithTableView:self.tableView];
102     cell.messageFrame = self.messages[indexPath.row];
103    
104     return cell;
105 }
106 
107 
108 #pragma mark - tableView代理方法
109 /** 动态设置每个cell的高度 */
110 - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
111     MessageFrame *messageFrame = self.messages[indexPath.row];
112     return messageFrame.cellHeight;
113 }
114 
115 #pragma mark - scrollView 代理方法
116 /** 点击拖曳聊天区的时候,缩回键盘 */
117 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
118     // 1.缩回键盘
119     [self.view endEditing:YES];
120 }
121 
122 
123 #pragma mark - 监听事件
124 - (void) keyboardWillChangeFrame:(NSNotification *) note {
125     // 1.取得弹出后的键盘frame
126     CGRect keyboardFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
127    
128     // 2.键盘弹出的耗时时间
129     CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
130    
131     // 3.键盘变化时,view的位移,包括了上移/恢复下移
132     CGFloat transformY = keyboardFrame.origin.y - self.view.frame.size.height;
133    
134     [UIView animateWithDuration:duration animations:^{
135         self.view.transform = CGAffineTransformMakeTranslation(0, transformY);
136     }];
137 }
138 
139 #pragma mark - TextField 代理方法
140 /** 回车响应事件 */
141 - (BOOL)textFieldShouldReturn:(UITextField *)textField {
142     // 我方发出信息
143     [self sendMessageWithContent:textField.text andType:MessageTypeMe];
144    
145     // 自动回复
146     [self sendMessageWithContent:[NSString stringWithFormat:@"%@\n%@", textField.text, @"你妹!!!"] andType:MessageTypeOhter];
147    
148     // 消除消息框内容
149     self.inputView.text = nil;
150    
151     [self.tableView reloadData];
152    
153     // 滚动到最新的消息
154     NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:self.messages.count - 1 inSection:0];
155     [self.tableView scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
156    
157     return YES; // 返回值意义不明
158 }
159 
160 // 发送消息
161 - (void) sendMessageWithContent:(NSString *) text andType:(MessageType) type {
162     // 获取当前时间
163     NSDate *date = [NSDate date];
164     NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
165     formatter.dateFormat = @"yyyy-MMM-dd hh:mm:ss";
166     NSString *dateStr = [formatter stringFromDate:date];
167    
168     // 我方发出信息
169     NSDictionary *dict = @{@"text":text,
170                            @"time":dateStr,
171                            @"type":[NSString stringWithFormat:@"%d", type]};
172    
173     Message *message = [[Message alloc] init];
174     [message setValuesForKeysWithDictionary:dict];
175     MessageFrame *messageFrame = [[MessageFrame alloc] init];
176     messageFrame.message = message;
177    
178     [self.messages addObject:messageFrame];
179 }
180 
181 @end
182  

 

工具类:
 1 //
 2 //  NSString+Extension.h
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 // NSString扩展类
 9 
10 #import <Foundation/Foundation.h>
11 #import <UIKit/UIKit.h>
12 
13 @interface NSString (Extension)
14 
15 /** 测量文本的尺寸 */
16 - (CGSize) sizeWithFont:(UIFont *)font maxSize:(CGSize) maxSize;
17 
18 @end
 
 1 //
 2 //  NSString+Extension.m
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "NSString+Extension.h"
10 
11 @implementation NSString (Extension)
12 
13 /** 测量文本的尺寸 */
14 - (CGSize)sizeWithFont:(UIFont *)font maxSize:(CGSize)maxSize {
15     NSDictionary *attrs = @{NSFontAttributeName: font};
16     CGSize size =  [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
17    
18     return size;
19 }
20 
21 @end
 
 1 //
 2 //  UIImage+Extension.h
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 // NSImage 类的扩展
 9 
10 #import <Foundation/Foundation.h>
11 #import <UIKit/UIKit.h>
12 
13 @interface UIImage (Extension)
14 
15 + (UIImage *) resizableImage:(NSString *) imageName;
16 
17 @end
18  

 

 1 //
 2 //  UIImage+Extension.m
 3 //  QQChatDemo
 4 //
 5 //  Created by hellovoidworld on 14/12/8.
 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "UIImage+Extension.h"
10 
11 @implementation UIImage (Extension)
12 
13 + (UIImage *) resizableImage:(NSString *) imageName {
14     UIImage *image = [UIImage imageNamed:imageName];
15     // 取图片中部的1 x 1进行拉伸
16     UIEdgeInsets insets = UIEdgeInsetsMake(image.size.height/2, image.size.width/2, image.size.height/2 + 1, image.size.width/2 + 1);
17     return [image resizableImageWithCapInsets:insets];
18 }
19 
20 @end

 

 
 

转载于:https://www.cnblogs.com/hellovoidworld/p/4152049.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/652291
推荐阅读
相关标签
  

闽ICP备14008679号