[iOS基础控件 - 6.9.1] 聊天界面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

 

 
 

你可能感兴趣的:(demo)