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


- //
- // 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 = , // 我发出的信息
- MessageTypeOhter = // 对方发出的信息
- } 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 = ;
- // 1.发送时间
- if (NO == message.hideTime) {
- CGFloat timeWidth = [UIScreen mainScreen].bounds.size.width;
- CGFloat timeHeight = ;
- CGFloat timeX = ;
- CGFloat timeY = ;
- _timeFrame = CGRectMake(timeX, timeY, timeWidth, timeHeight);
- }
- // 2.头像
- CGFloat iconWidth = ;
- CGFloat iconHeight = ;
- // 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 * , MAXFLOAT);
- // 3.2 计算文本真实尺寸
- CGSize textRealSize = [message.text sizeWithFont:MESSAGE_TEXT_FONT maxSize:textMaxSize];
- // 3.3 按钮尺寸
- CGSize btnSize = CGSizeMake(textRealSize.width + TEXT_INSET*, textRealSize.height + TEXT_INSET*);
- // 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
- //
- // 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:]; // 设置自动换行
- // 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
- //
- // 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(, , , )];
- 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(, 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 - inSection:];
- [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/, image.size.width/, image.size.height/ + , image.size.width/ + );
- return [image resizableImageWithCapInsets:insets];
- }
- @end
[iOS基础控件 - 6.9.1] 聊天界面Demo 代码的更多相关文章
- [iOS基础控件 - 6.11.3] 私人通讯录Demo 控制器的数据传递、存储
A.需求 1.搭建一个"私人通讯录"Demo 2.模拟登陆界面 账号 密码 记住密码开关 自动登陆开关 登陆按钮 3.退出注销 4.增删改查 5.恢复数据(取消修改) 这个代码 ...
- [iOS基础控件 - 3.1] QQ登陆界面
A.storyboard 控件版 1.label 2.textfield a.Keyboard Type 账号:Number Pad 密码:Num ...
- [iOS基础控件 - 5.5] 代理设计模式 (基于”APP列表"练习)
A.概述 在"[iOS基础控件 - 4.4] APP列表 进一步封装,初见MVC模式”上进一步改进,给“下载”按钮加上效果.功能 1.按钮点击后,显示为“已下载”,并且不 ...
- [iOS基础控件 - 6.9] 聊天界面Demo
A.需求 做出一个类似于QQ.微信的聊天界面 1.每个cell包含发送时间.发送人(头像).发送信息 2.使用对方头像放在左边,我方头像在右边 3.对方信息使用白色背景对话框,我方信息使用蓝色背景对话 ...
- iOS 基础控件(下)
上篇介绍了UIButton.UILabel.UIImageView和UITextField,这篇就简短一点介绍UIScrollView和UIAlertView. UIScrollView 顾名思义也知 ...
- [iOS基础控件 - 7.0] UIWebView
A.基本使用 1.概念 iOS内置的浏览器控件 Safari浏览器就是通过UIWebView实现的 2.用途:制作简易浏览器 (1)基本请求 创建请求 加载请求 (2)代理监听webView加载, ...
- [iOS基础控件 - 6.10.2] PickerView 自定义row内容 国家选择Demo
A.需求 1.自定义一个UIView和xib,包含国家名和国旗显示 2.学习row的重用 B.实现步骤 1.准备plist文件和国旗图片 2.创建模型 // // Flag.h // Co ...
- iOS基础 - 控件属性
一.控件的属性 1.CGRect frame 1> 表示控件的位置和尺寸(以父控件的左上角为坐标原点(0, 0)) 2> 修改这个属性,可以调整控件的位置和尺寸 2.CGPoint cen ...
- [iOS基础控件 - 6.12.3] @property属性 strong weak copy
A.概念 @property 的修饰词 strong: 强指针/强引用(iOS6及之前是retain) weak: 弱智真/弱引用(iOS6及之前是assign) 默认情况所有指针都是强指针 ...
随机推荐
- Java开发之反射的使用
通过类名获取类. Class serviceManager = Class.forName("android.os.ServiceManager"); 获取方法 Method me ...
- 【笨嘴拙舌WINDOWS】伟大的变革
"改革"."革命"."变革" 这几个词语毫无疑问是每一个时代必须被呼吁的词语,当一个国家没有人求变时,那是一个时代的悲剧.无论是文景之治,贞 ...
- Qt之运行一个实例进程
简述 发布程序的时候,我们往往会遇到这种情况: 只需要用户运行一个实例进程 用户可以同时运行多个实例进程 一个实例进程的软件有很多,例如:360.酷狗- 多个实例进程的软件也很多,例如:Visual ...
- AssetManager asset的使用
Android 系统为每个新设计的程序提供了/assets目录,这个目录保存的文件可以打包在程序里./res 和/assets的不同点是,android不为/assets下的文件生成ID.如果使用/a ...
- System.web.optimization 在 Asp.Net WebForm 中应用得注意了
我们也可以在Asp.Net WebForm项目中去使用Optimization,去处理我们的资源文件,从而起到优化网站性能的效果,前端知识得从小事做起.但是在使用过程中我却发现了下面的问题. 第一步: ...
- RESTful API 设计最佳实践(转)
背景 目前互联网上充斥着大量的关于RESTful API(为方便,下文中“RESTful API ”简写为“API”)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API 格式如何?你的 ...
- shell -Z- d等等代表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 [ -a FILE ] ...
- Android手动画柱状图的例子
效果图如上,网上看到的例子,谨以此文记录一下,以后用到的地方再来翻翻. 核心技术是用Canvas和Paint画长方形. 源码地址:http://download.csdn.net/detail/abc ...
- hdu 2059(dp)
题意:容易理解... 思路:dp[i]表示乌龟到达第i个充电站时最少花费时间到第 i 个充电站后,从起点开始遍历到第 i-1 个充电站,得到最少花费时间 状态转移方程:dp[i]=min(dp[j]+ ...
- 22、TTS技术
Android对TTS技术的支持 Android 1.6开始支持TTS(Text To Speech)技术,通过该技术可以将文本转换成语音. TTS技术的核心是android.speech.tts.T ...