简单版QQ聊天
来源:互联网 发布:吾知所以距子矣的距 编辑:程序博客网 时间:2024/04/18 13:36
这个小的应用中主要用到了 MVC的开发模式, 还有 代理和通知机制
这个程序中包含了2个模型 modle 和modleframe
modle中存放的是 每一条消息的详细内容
modle类
typedef enum
{
JMMessageModelTypeMe =0,
JMMessageModelTypeOther
}JMMessageModelType;
@interface JMgessageModle :NSObject
@property (nonatomic,copy)NSString *text; //信息内容
@property (nonatomic,copy)NSString *time; //发送时间
@property (nonatomic,assign) JMMessageModelType type; //头像的的宏, 0是自己,1是他人
@property (nonatomic,assign) BOOL hiddenTime; //是否显示时间,当俩条小时是一样的时候就隐藏时间
- (instancetype)initWithDict:(NSDictionary *)dict; //字典转模型的方法
+ (instancetype)modeWithDict:(NSDictionary *)dict; //工厂方法
@end
#import "JMgessageModle.h"
@implementation JMgessageModle
- (instancetype)initWithDict:(NSDictionary *)dict;
{
if(self = [superinit])
{
[selfsetValuesForKeysWithDictionary:dict]; //KVC机制使成员变量和字段中得值,自动对应起来
}
return self;
}
+ (instancetype)modeWithDict:(NSDictionary *)dict; //类方法,(工厂方法)
{
return [[selfalloc]initWithDict:dict];
}
@end
modleframe类
#import <Foundation/Foundation.h> //用来设置每个modle的位置(大小和位置)
@class JMgessageModle;
@interface JMgessageModleFrame :NSObject
#define JMTextFont [UIFont systemFontOfSize:15]
//设置每个modle的位置与大小
//声明一个模型属性
@property (nonatomic,strong) JMgessageModle *gessage;
//设置时间的位置
@property (nonatomic,assign,readonly)CGRect timeF;
//设置头像的位置
@property (nonatomic,assign,readonly)CGRect iconF;
//设置正文的位置
@property (nonatomic,assign,readonly)CGRect textF;
//设置cell的
@property (nonatomic,assign,readonly)CGFloat cellHeight;
@end
#import "JMgessageModleFrame.h"
#import "JMgessageModle.h"
@implementation JMgessageModleFrame
//重写magest的set方法给每个模型设置位置和大小
- (void)setGessage:(JMgessageModle *)gessage
{
//千万不要忘记给属性赋值,这个错误很坑爹的
_gessage = gessage;
//获取屏幕的宽度,
CGFloat screenWidth = [UIScreenmainScreen].bounds.size.width;
//table 距离两边的间隙
CGFloat padding = 10;
//1 时间的设置
if(NO == gessage.hiddenTime)
{
CGFloat timeX =0; //时间是放爱一个lable中得,里面的文字居中就行,所以在这里不用设
CGFloat timeY = 0;
CGFloat timeW = screenWidth;
CGFloat timeH = 30;
_timeF = CGRectMake(timeX, timeY, timeW, timeH);
}
//2 头像的位置
CGFloat iconX =0; //时间是放爱一个lable中得,里面的文字居中就行,所以在这里不用设
CGFloat iconY =CGRectGetMaxY(_timeF) + padding;//因为头像在时间的下面,所以,就取是时间的Y值再加上间隙
CGFloat iconW = 30;
CGFloat iconH = 30;
//头像的位置首先判断一下,这个头像是自检的还是别人的,自己的在左边,别人的就再右边
if(JMMessageModelTypeMe== _gessage.type)
{
iconX = screenWidth - padding -iconW;
}
else //他人得头像, 就是一个间隙
{
iconX = padding;
}
_iconF = CGRectMake(iconX, iconY, iconH, iconW);
//3 正文的位置
NSDictionary *dict =@{NSFontAttributeName:JMTextFont};//JMTextFont是个宏,设置字体大小
//给下面的那个计算文字高度的方法,设置文字的字体,
CGSize maxSize = CGSizeMake(200,MAXFLOAT);// 设置要显示文字的宽度,高不限制
//
CGSize textSize = [_gessage.textboundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dictcontext:nil].size;
CGFloat textW = textSize.width +40;
CGFloat textH = textSize.height +40;
CGFloat textY = iconY;
CGFloat textX = 0;
if (JMMessageModelTypeMe ==_gessage.type) {
// 自己发的
// x = 头像x - 间隙 - 文本的宽度
textX = iconX - padding - textW;
}else
{
// 别人发的
// x = 头像最大的X + 间隙
textX =CGRectGetMaxX(_iconF) + padding;
}
_textF = CGRectMake(textX, textY, textW, textH);
//行高
CGFloat maxIconY = CGRectGetMaxY(_iconF);
CGFloat maxTextY = CGRectGetMaxY(_textF);
// _cellHeight = (maxIconY > maxTextY? (maxIconY + padding) : (maxIconY + padding));
_cellHeight = MAX(maxIconY, maxTextY) + padding;
}
@end
#import "JMgessageModleFrame.h"
#import <UIKit/UIKit.h>
@interface JMmessageCell :UITableViewCell
+ (instancetype)cellWithTableView:(UITableView *)tableView;//重写cellwith方法
@property (nonatomic,strong) JMgessageModleFrame *messageFrame;
@end
#import "JMmessageCell.h"
#import "JMgessageModleFrame.h"
#import "JMgessageModle.h"
@interface JMmessageCell()
@property (nonatomic,weak)UILabel *timeLable;//给cell中设置一个显示时间的控件
@property (nonatomic,weak)UIImageView *imangeView;// 头像
@property (nonatomic,weak)UIButton *textButton;
@end
@implementation JMmessageCell
+ (instancetype)cellWithTableView:(UITableView *)tableView//创建cell
{
static NSString *identifier =@"message";
JMmessageCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[JMmessageCellalloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:identifier];
}
return cell;
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
//添加所有需要显⽰示的⼦子控件(不需要设置⼦子控件的数据和frame,⼦子控件要添加 到contentView中)重写这个方法的意思就是重新购置一个Cell 自己定义一个cell的风格
self = [superinitWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
//设置时间的样式 :因为每行都有一个显示时间的控件
UILabel *timeLabel = [[UILabelalloc]init];
timeLabel.font = [UIFontsystemFontOfSize:13.0];//设置字体
timeLabel.textAlignment =NSTextAlignmentCenter;//设置居中对齐
//timeLabel.backgroundColor = [UIColor grayColor];//这种背景颜色
[self.contentViewaddSubview:timeLabel]; //把控件添加到控制器中
self.timeLable = timeLabel;
// 2.添加正文
UIButton *contentBtn = [[UIButtonalloc] init];//设置正文按钮
contentBtn.titleLabel.font =JMTextFont; //这种字体
[contentBtn setTitleColor:[UIColorblackColor] forState:UIControlStateNormal];
// 设置自动换行
contentBtn.titleLabel.numberOfLines =0;
[self.contentViewaddSubview:contentBtn];
_textButton = contentBtn;
// 3.添加头像
UIImageView *iconView = [[UIImageViewalloc] init];
[self.contentViewaddSubview:iconView];
_imangeView = iconView;
// 4.清空cell的背景颜色
self.backgroundColor = [UIColorclearColor];
self.textButton.contentEdgeInsets =UIEdgeInsetsMake(20,20, 20, 20);
}
return self;
}
- (void)setMessageFrame:(JMgessageModleFrame *)messageFrame
{
_messageFrame = messageFrame;//传入一个模型坐标
/*
5.重写frame模型属性的setter⽅方法:在这个⽅方法中设置⼦子控件的显⽰示数据和frame
// 1.设置子控件的数据
[self settingData];
// 2.设置子控件的frame
[self settingFrame];
NSLog(@"%@_________%@---%d", messagea.text,messagea.time,messagea.type);
*/
// 0. 获取数据模型
JMgessageModle *mange =_messageFrame.gessage;
// 1.设置时间的值与位置
self.timeLable.text = mange.time;
self.timeLable.frame =_messageFrame.timeF;
// 2 设置头像
if(JMMessageModelTypeMe == mange.type)
{
self.imangeView.image = [UIImageimageNamed:@"me"];
}
else
{
self.imangeView.image = [UIImageimageNamed:@"other"];
}
self.imangeView.frame =_messageFrame.iconF;
// 3 设置文字
[self.textButtonsetTitle:mange.textforState:UIControlStateNormal];
self.textButton.frame =_messageFrame.textF;
//设置背景图片
if (JMMessageModelTypeMe == mange.type)
{
// 自己发的
UIImage *norImage = [UIImageimageNamed:@"chat_send_nor"];
CGFloat w = norImage.size.width *0.5;
CGFloat h = norImage.size.height *0.5;
UIImage *newImage = [norImageresizableImageWithCapInsets:UIEdgeInsetsMake(h, w, h, w)resizingMode:UIImageResizingModeStretch];
[self.textButtonsetBackgroundImage:newImage forState:UIControlStateNormal];
}
else
{
UIImage *norImage = [UIImageimageNamed:@"chat_recive_nor"];
CGFloat w = norImage.size.width *0.5;
CGFloat h = norImage.size.height *0.5;
UIImage *newImage = [norImageresizableImageWithCapInsets:UIEdgeInsetsMake(h, w, h, w)resizingMode:UIImageResizingModeStretch];
[self.textButtonsetBackgroundImage:newImage forState:UIControlStateNormal];
}
}
@end
//
// JMViewController.m
// QQ聊天
//
// Created by wjm on 14-5-28.
// Copyright (c) 2014年 itheima. All rights reserved.
//
#import "JMgessageModle.h"
#import "JMgessageModleFrame.h"
#import "JMViewController.h"
#import "JMmessageCell.h"
@interface JMViewController ()<UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate>
@property (nonatomic,weak)IBOutlet UITableView *tableView;
@property (nonatomic,strong)NSMutableArray *messages;
@property (nonatomic,strong)NSDictionary *aggess;
@property (weak, nonatomic) IBOutletUITextField *inputTextField;
@end
@implementation JMViewController
//懒加载
- (NSMutableArray *)messages
{
if (_messages ==nil) {
NSString *fullPath = [[NSBundlemainBundle] pathForResource:@"messages.plist"ofType:nil];
NSArray *dictArray = [NSArrayarrayWithContentsOfFile:fullPath];
NSMutableArray *models = [NSMutableArrayarrayWithCapacity:dictArray.count];
JMgessageModle *previousMessage = nil;
for (NSDictionary *dictin dictArray) {
// 创建数据模型
JMgessageModle *messagea11 = [JMgessageModlemodeWithDict:dict];
//获取上一次的时间
// 创建frame模型
messagea11.hiddenTime = [messagea11.timeisEqualToString:previousMessage.time];
JMgessageModleFrame *mfm = [[JMgessageModleFramealloc] init];
mfm.gessage = messagea11;
[modelsaddObject:mfm];
previousMessage = messagea11;
}
self.messages = [modelsmutableCopy];
}
return _messages;
}
//懒加载2
- (NSDictionary *)aggess
{
if (_aggess ==nil) {
NSString *fullPath = [[NSBundlemainBundle] pathForResource:@"aggess.plist"ofType:nil];
_aggess = [NSDictionarydictionaryWithContentsOfFile:fullPath];
}
return_aggess;
}
- (void)viewDidLoad
{
[superviewDidLoad];
self.tableView.rowHeight =100;
self.tableView.dataSource =self;
// 设置隐藏分割线
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
//设置隐藏垂直的滚动条
self.tableView.showsVerticalScrollIndicator =NO;
self.tableView.allowsSelection =NO;
// 设置tableview的背景颜色
self.tableView.backgroundColor = [UIColorcolorWithRed:224/255.0green:224/255.0blue:224/255.0alpha:1];
[[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector(keyboardWillChange:)name:UIKeyboardWillChangeFrameNotification object:nil];
UIView *view = [[UIViewalloc] initWithFrame:CGRectMake(0,0, 5, 0)];//输入框光标到右边的距离
// view.backgroundColor = [UIColor redColor];
self.inputTextField.leftView = view;
//设置左边视图的显示模式
self.inputTextField.leftViewMode = UITextFieldViewModeAlways;
// 监听键盘send按钮的点击
self.inputTextField.delegate =self;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField//键盘输入文本的操作
{
[selfaddMessage:textField.texttype:JMMessageModelTypeMe];
NSString *result = nil;
for (int i =0; i < textField.text.length; i++)
{
NSString *str = [textField.textsubstringWithRange:NSMakeRange(i,1)];
result =self.aggess[str];
if(result != nil)
{
break;
}else{
result =[NSStringstringWithFormat:@"%@个毛线啊" , textField.text];
}
}
//NSString *str = [NSString stringWithFormat:@"%@个毛线啊" , textField.text];
[selfaddMessage:result type:JMMessageModelTypeOther];
[self.tableViewreloadData]; //清除数据
textField.text =nil;
NSIndexPath * indexpath = [NSIndexPathindexPathForRow:self.messages.count-1inSection:0];
[self.tableViewscrollToRowAtIndexPath:indexpath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
return YES;
}
- (void)addMessage:(NSString *)content type:(JMMessageModelType)type
{
// 1.修改模型(创建模型,并且将模型保存到数组中)
NSDate *date = [NSDatedate];//获取系统时间
NSDateFormatter *datestyle = [[NSDateFormatteralloc] init];//创建一个时间系那是公式
datestyle.dateFormat =@"HH:mm:ss:dd/MM";//时间格式
NSString *content1 = [datestyle stringFromDate:date];//把时间按这个格式显示出来
JMgessageModle *message = [[JMgessageModlealloc]init];//新建一个modle类
message.time =content1;
message.text = content;
message.type = type;
JMgessageModleFrame *modleframe = [[JMgessageModleFramealloc]init];
modleframe.gessage = message;
[self.messagesaddObject:modleframe];//把这个modleframe添加到模型数组中
// 获取上一次的message
}
- (void)keyboardWillChange:(NSNotification *)notification //键盘控制器
{
NSDictionary *dict = notification.userInfo;
CGRect keyboardFrame = [dict[UIKeyboardFrameEndUserInfoKey]CGRectValue];
CGFloat keyboardY = keyboardFrame.origin.y;
//获取动画执行时间
CGFloat duration = [dict[UIKeyboardAnimationDurationUserInfoKey]doubleValue];
// 2.计算需要移动的距离
CGFloat translationY = keyboardY - self.view.frame.size.height;
// 通过动画移动view
输入框和键盘之间会由一条黑色的线条,产生线条的原因是键盘弹出时执行动画的节奏和我们让控制器view移动的动画的节奏不一致导致
*/
[UIViewanimateWithDuration:duration delay:0.0options:7 <<16 animations:^{
// 需要执行动画的代码
self.view.transform = CGAffineTransformMakeTranslation(0, translationY);
}completion:^(BOOL finished) {
// 动画执行完毕执行的代码
}];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.messages.count; //tableView的组数
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.创建cell
JMmessageCell *cell = [JMmessageCellcellWithTableView:tableView];
// 2.设置数据
cell.messageFrame =self.messages[indexPath.row];
// 3.返回cell
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.取出frame模型
JMgessageModleFrame *mf =self.messages[indexPath.row];
// 2.返回对应行的高度
return mf.cellHeight;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self.viewendEditing:YES];//隐藏键盘
}
- (BOOL)prefersStatusBarHidden
{
return YES; //状态栏不显示
}
@end
- 简单版QQ聊天
- 简单模拟qq聊天程序(TCP版)
- 一个简单的QQ聊天代码
- 简单QQ网络聊天机程序
- listview简单实现QQ聊天栏侧滑
- 简单的QQ临时在线聊天功能
- 【HTML5】简单实现QQ聊天气泡效果
- qq聊天
- QQ聊天
- QQ聊天
- QQ聊天
- Qt程序聊天弹屏问题简单解决方法(类似QQ聊天聊天窗口弹屏)
- 30秒自制简单程序,和任意QQ号码聊天
- 30秒自制简单程序,和任意QQ号码聊天
- webqq2协议分析和qq聊天机器人简单实现
- Java之Socket简单聊天实现(QQ续二)
- webqq2协议分析和qq聊天机器人简单实现
- Java之Socket简单聊天实现(QQ续二)
- Codeforces Round #250 Div. 2(C.The Child and Toy)
- 珍爱,你懂的
- Android TextView内容过长加省略号,点击显示全部内容
- 【Android进阶】如何使用文件来保存程序中的数据
- google推出的SwipeRefreshLayout下拉刷新用法
- 简单版QQ聊天
- 环境变量
- android数据对外共享的方式----contentProvider
- 电感磁芯公式
- OpenCV2马拉松第25圈——直线拟合与RANSAC算法
- mysql 启动错误集锦
- 情殇
- DEMO阶段已经完成,现在应该往深里钻了
- KMP算法的工作流程介绍