***********controller.m

#import "HMViewController.h"
#import "HMMessageModel.h"
#import "HMMessageCell.h"
#import "HMMessageFrameModel.h"
@interface HMViewController ()<UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITextField *inputView; @property (nonatomic, strong)NSMutableArray *messages; //自动回复数组
@property (nonatomic, strong)NSDictionary *autoReplay; @property (weak, nonatomic) IBOutlet UITableView *tableView;
@end @implementation HMViewController - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. //cell 不可选中
self.tableView.allowsSelection = NO; self.tableView.backgroundColor = [UIColor colorWithRed:/255.0 green:/255.0 blue:/255.0 alpha:1.0]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; //设置做边距
self.inputView.leftView = [[UIView alloc]initWithFrame:CGRectMake(, , , )];
//一直显示
self.inputView.leftViewMode = UITextFieldViewModeAlways;
} //懒加载自动回复
- (NSDictionary *)autoReplay
{
if (_autoReplay == nil) {
_autoReplay = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"autoReplay.plist" ofType:nil]];
} return _autoReplay;
} //点击右下角的send 按钮
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSLog(@"-------%@",textField.text); //1. 发送一条数据
[self addmessage:textField.text type:HMMessageModelGatsby];
//自动回复
NSString *autoStr = [self autoReplayWithText:textField.text];
//将自动回复添加成一天聊天信息
[self addmessage:autoStr type:HMMessageModelJobs];
//4. 清空表格 self.inputView.text = @"";//nil //直接return yes 即可
return YES;
}
//自动回复一条聊天信息 - (NSString *)autoReplayWithText:(NSString *)text
{
//3自动回复
for (int a = ; a < text.length; a++) { NSString *subStr = [text substringWithRange:NSMakeRange(a, )]; if (self.autoReplay[subStr]) {// 不是空,返回plist对应的数据
return self.autoReplay[subStr];
}
} return @"滚蛋吗0";
} //添加一条聊天信息 - (void)addmessage:(NSString *)text type:(HMMessageModelType)type
{
//1. 添加模型数据
HMMessageModel *msg = [[HMMessageModel alloc]init]; //设置数据的值
msg.time = @"16:88";
msg.text = text;
msg.type = type; //设置内容的frame
HMMessageFrameModel *fm = [[HMMessageFrameModel alloc]init];
//将msg 赋值给 fm 中的message
fm.message = msg;
[self.messages addObject:fm]; //2.刷新表格
[self.tableView reloadData]; //3. 自动上移
//移动的位置
NSIndexPath *path = [NSIndexPath indexPathForRow:self.messages.count - inSection:];
//真正去是位置 atSrcollPosition : 滚到位置
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } // UIKeyboardAnimationCurveUserInfoKey = 7; 动画曲线动画
// UIKeyboardAnimationDurationUserInfoKey = "0.25"; 动画时间
// UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}"; 键盘bounds
// UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}"; 开始键盘的居中位置
// UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";结束键盘的居中位置
// UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}"; 键盘开始弹出的frame
// UIKeyboardFrameChangedByUserInteraction = 0; 键盘改变frame
// UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}"; 退出键盘的frame // UIKeyboardAnimationCurveUserInfoKey = 7;
// UIKeyboardAnimationDurationUserInfoKey = "0.25";
// UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";
// UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 372}";
// UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 588}";
// UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";
// UIKeyboardFrameChangedByUserInteraction = 0;
// UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}"; //当键盘frame 发生改变的时候调用
- (void)keyboardDidChangeFrame:(NSNotification *)noti
{
NSLog(@"--------%@",noti.userInfo); //改变window的背景颜色
self.view.window.backgroundColor = self.tableView.backgroundColor; //最终键盘的frame
CGRect frame = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; //键盘实时y
CGFloat keyY = frame.origin.y; //屏幕的高度
CGFloat screenH = [[UIScreen mainScreen] bounds].size.height; //动画时间
CGFloat keyDuration = [noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue]; //执行动画
[UIView animateWithDuration:keyDuration animations:^{
self.view.transform = CGAffineTransformMakeTranslation(, keyY - screenH);
}]; } //当tableview 滚动的时候 结束编辑事件 (退出键盘)
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self.view endEditing:YES];
} - (NSMutableArray *)messages
{
if (_messages == nil) { NSArray * array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil]]; NSMutableArray *messageArr = [NSMutableArray array];
for (NSDictionary *dict in array) {
HMMessageModel *messga = [HMMessageModel messageWithDict:dict]; //取出上一个模型
HMMessageFrameModel *lastFm = [messageArr lastObject]; //隐藏时间
messga.hideTime = [messga.time isEqualToString:lastFm.message.time]; HMMessageFrameModel *fm = [[HMMessageFrameModel alloc]init];
fm.message = messga; [messageArr addObject:fm];
} _messages = messageArr;
} return _messages;
}
//隐藏状态栏
- (BOOL)prefersStatusBarHidden
{
return YES;
} #pragma mark tableview数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.messages.count;
} - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
HMMessageFrameModel *model = self.messages[indexPath.row];
return model.cellH;//cell 的高度
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//初始化cell
HMMessageCell *cell = [HMMessageCell messageCellWithTableView:tableView];
//取出model
HMMessageFrameModel *model = self.messages[indexPath.row];
//设置model
cell.frameMessage = model; return cell;
} - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end
#import <UIKit/UIKit.h>

@interface HMViewController : UIViewController

@end

***cell.h

#import <UIKit/UIKit.h>
@class HMMessageFrameModel;
@interface HMMessageCell : UITableViewCell + (instancetype)messageCellWithTableView:(UITableView *)tableview; //frame 的模型
@property (nonatomic, strong)HMMessageFrameModel *frameMessage; @end

*****cell.m

#import "HMMessageCell.h"
#import "HMMessageFrameModel.h"
#import "HMMessageModel.h"
#import "Constant.h"
#import "UIImage+ResizImage.h"
@interface HMMessageCell()
//时间
@property (nonatomic, weak)UILabel *time;
//正文
@property (nonatomic, weak)UIButton *textView;
//用户头像
@property (nonatomic, weak)UIImageView *icon; @end @implementation HMMessageCell
+ (instancetype)messageCellWithTableView:(UITableView *)tableview
{
static NSString *ID = @"messageCell";
HMMessageCell *cell = [tableview dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[self alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
} return cell;
} - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//1.时间
UILabel *time = [[UILabel alloc]init];
time.textAlignment = NSTextAlignmentCenter;
time.font = [UIFont systemFontOfSize:13.0f];
[self.contentView addSubview:time];
self.time = time; //1.正文
UIButton *textView = [[UIButton alloc]init];
textView.titleLabel.font = bBtnFont;
textView.titleLabel.numberOfLines = ;//自动换行
textView.contentEdgeInsets = UIEdgeInsetsMake(, , , );
[textView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.contentView addSubview:textView];
self.textView = textView; //1.头像
UIImageView *icon = [[UIImageView alloc]init];
[self.contentView addSubview:icon];
self.icon = icon; self.backgroundColor = [UIColor clearColor]; }
return self;
} //设置内容和frame
- (void)setFrameMessage:(HMMessageFrameModel *)frameMessage
{
_frameMessage = frameMessage; HMMessageModel *model = frameMessage.message; //1.时间
self.time.frame = frameMessage.timeF;
self.time.text = model.time; //2.头像
self.icon.frame = frameMessage.iconF;
if (model.type == HMMessageModelGatsby) {
self.icon.image = [UIImage imageNamed:@"Gatsby"];
}else{
self.icon.image = [UIImage imageNamed:@"Jobs"];
} //3.正文
self.textView.frame = frameMessage.textViewF;
[self.textView setTitle:model.text forState:UIControlStateNormal]; if (model.type == HMMessageModelGatsby) {
// [self.textView setBackgroundImage:[self resizeWithImageName:@"chat_send_nor"] forState:UIControlStateNormal]; [self.textView setBackgroundImage:[UIImage resizeWithImageName:@"chat_send_nor"] forState:UIControlStateNormal];
}else{
[self.textView setBackgroundImage:[UIImage resizeWithImageName:@"chat_recive_nor"] forState:UIControlStateNormal];
} } //返回一个可拉伸的图片 @end

medel.h

#import <Foundation/Foundation.h>
typedef enum {
HMMessageModelGatsby = ,//Gatsby
HMMessageModelJobs//Jobs
}HMMessageModelType;
@interface HMMessageModel : NSObject //正文
@property (nonatomic, copy)NSString *text; //时间
@property (nonatomic, copy)NSString *time; //发送类型
@property (nonatomic, assign)HMMessageModelType type; //是否隐藏时间
@property (nonatomic,assign)BOOL hideTime; - (instancetype)initWithDict:(NSDictionary *)dict; + (instancetype)messageWithDict:(NSDictionary *)dict; @end

model.m

#import "HMMessageModel.h"

@implementation HMMessageModel

- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
} return self;
} + (instancetype)messageWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
} @end

**modelFrame.h

#import <Foundation/Foundation.h>
@class HMMessageModel;
@interface HMMessageFrameModel : NSObject //时间的frame
@property (nonatomic, assign,readonly)CGRect timeF; //正文的frame
@property (nonatomic, assign,readonly)CGRect textViewF; //图片
@property (nonatomic, assign,readonly)CGRect iconF; //cell
@property (nonatomic, assign,readonly)CGFloat cellH; //数据模型
@property (nonatomic, strong)HMMessageModel *message;
@end

****modelFrame.m

#import "HMMessageFrameModel.h"
#import "Constant.h"
#import "HMMessageModel.h"
@implementation HMMessageFrameModel - (void)setMessage:(HMMessageModel *)message
{
_message = message; CGFloat padding = ;
//1. 时间
if (message.hideTime == NO) {
CGFloat timeX = ;
CGFloat timeY = ;
CGFloat timeW = bScreenWidth;
CGFloat timeH = bNormalH; _timeF = CGRectMake(timeX, timeY, timeW, timeH);
} //2.头像
CGFloat iconX;
CGFloat iconY = CGRectGetMaxY(_timeF);
CGFloat iconW = bIconW;
CGFloat iconH = bIconH; if (message.type == HMMessageModelGatsby) {//自己发的 iconX = bScreenWidth - iconW - padding; }else{//别人发的
iconX = padding;
} _iconF = CGRectMake(iconX, iconY, iconW, iconH);
//3.正文 CGFloat textX;
CGFloat textY = iconY+ padding; CGSize textMaxSize = CGSizeMake(, MAXFLOAT);
CGSize textRealSize = [message.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:bBtnFont} context:nil].size; CGSize btnSize = CGSizeMake(textRealSize.width + , textRealSize.height + ); if (message.type == HMMessageModelGatsby) {
textX = bScreenWidth - iconW - padding* - btnSize.width;
}else{
textX = padding + iconW;
} // _textViewF = CGRectMake(textX, textY, <#CGFloat width#>, <#CGFloat height#>)
_textViewF = (CGRect){{textX,textY},btnSize}; //4.cell高度 CGFloat iconMaxY = CGRectGetMaxY(_iconF);
CGFloat textMaxY = CGRectGetMaxY(_textViewF); _cellH = MAX(iconMaxY, textMaxY); } @end

附录:

#define bScreenWidth [[UIScreen mainScreen] bounds].size.width

#define bNormalH 44

#define bIconW 50

#define bIconH 50

#define bBtnFont [UIFont systemFontOfSize:15.0f]

#define bBtnPadding 20

//缩放

#import "UIImage+ResizImage.h"

@implementation UIImage (ResizImage)

+ (UIImage *)resizeWithImageName:(NSString *)name
{
UIImage *normal = [UIImage imageNamed:name]; // CGFloat w = normal.size.width * 0.5f ;
// CGFloat h = normal.size.height *0.5f ; CGFloat w = normal.size.width*0.5;
CGFloat h = normal.size.height*0.5;
//传入上下左右不需要拉升的边距,只拉伸/填铺中间部分
return [normal resizableImageWithCapInsets:UIEdgeInsetsMake(h, w, h, w)]; // [normal resizableImageWithCapInsets:UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)] // 1 = width - leftCapWidth - right
// 1 = height - topCapHeight - bottom //传入上下左右不需要拉升的编剧,只拉伸中间部分,并且传入模式(平铺/拉伸)
// [normal :<#(UIEdgeInsets)#> resizingMode:<#(UIImageResizingMode)#>] //只用传入左边和顶部不需要拉伸的位置,系统会算出右边和底部不需要拉升的位置。并且中间有1X1的点用于拉伸或者平铺
// 1 = width - leftCapWidth - right
// 1 = height - topCapHeight - bottom
// return [normal stretchableImageWithLeftCapWidth:w topCapHeight:h];
} @end

IOS第九天(2:QQ聊天界面键盘优化 和自动回复)的更多相关文章

  1. IOS第九天(3:QQ聊天界面通知的使用)

    #import <Foundation/Foundation.h> #import "Person.h" #import "XQCompany.h" ...

  2. IOS第九天(1:QQ聊天界面frame模型)

    ///  控制层 #import "HMViewController.h" #import "HMMessageModel.h" #import "H ...

  3. QQ聊天界面的布局和设计(IOS篇)-第二季

    QQChat Layout - 第二季 本来第二季是快写好了, 也花了点功夫, 结果gitbook出了点问题, 给没掉了.有些细节可能会一带而过, 如有疑问, 相互交流进步~. 在第一季中我们完成了Q ...

  4. QQ聊天界面的布局和设计(IOS篇)-第一季

    我写的源文件整个工程会再第二季中发上来~,存在百度网盘, 感兴趣的童鞋, 可以关注我的博客更新,到时自己去下载~.喵~~~ QQChat Layout - 第一季 一.准备工作 1.将假数据messa ...

  5. Objective-c——UI基础开发第八天(QQ聊天界面)

    一.知识点: QQ聊天界面 双模型的使用(dataModel和frameModel) UITextField的使用 通知的使用 拉伸图片的两种方法(slicing/image对象的resizeable ...

  6. 高仿qq聊天界面

    高仿qq聊天界面,给有需要的人,界面效果如下: 真心觉得做界面非常痛苦,给有需要的朋友. chat.xml <?xml version="1.0" encoding=&quo ...

  7. IOS开发学习笔记043-QQ聊天界面实现

    QQ聊天界面实现 效果如下: 实现过程: 1.首先实现基本界面 头像使用 UIImageView : 文字消息使用 UIButton 标签使用 UILable :水平居中 所有元素在一个cell中,在 ...

  8. 在WEB项目中调用QQ通讯组件打开QQ聊天界面

    在很多WEB项目中,需要提供在线服务的功能,加上自己的联系方式,例如:QQ,不用添加QQ好友也可以交谈,那这到底是怎么实现的呢? 对于这个功能,需要提到一个组件,即“QQ通讯组件”.QQ通讯组件是一种 ...

  9. Android 内部启动其他应用,以及打开指定qq聊天界面

    在自己应用中打开第三方应用,有好多种方法,这里举例一种: //以打开微信为例,前提需要知道打开应用的包名,一般一个发布版本的应用,包名不会轻易改变的,但是,打开QQ就要注意了,毕竟QQ的发布版本有不下 ...

随机推荐

  1. Angular JS 学习之过滤器

    1.过滤器可以使用一个管道字符(|)添加到表达式和指令中: 2.AngularJS过滤器可用于转换数据: **currency:格式化数字为货币格式: **filter:从数组项中选择一个子集: ** ...

  2. POJ 2549 二分+HASH

    题目链接:http://poj.org/problem?id=2002 题意:给定一个n个数字组成的序列,然后求出4个数使得a+b+c=d,求d的最大值.其中a,b,c,d要求是给定序列的数,并且不能 ...

  3. spring 干嘛用的,记录。以后用多了再补充

    http://zhidao.baidu.com/link?url=TVePPDbQU1n61s_Bu2FT9_YoJebaux8tYlNEZQhiHYHpT8QIbbyOSC8wDnpVmnmurwN ...

  4. web开发的基础知识:http请求

    引用自:http://blog.csdn.net/yefan2222/article/details/6198098 http://baike.baidu.com/view/1628025.htm?f ...

  5. 安装SQL2008 提示 创建usersettings/microsoft.sqlserver.configuration.landingpage.properties.se

    System.Configuration.ConfigurationErrorsException: 创建 userSettings/Microsoft.SqlServer.Configuration ...

  6. CF#335 Lazy Student

    Lazy Student time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  7. BZOJ4569 : [Scoi2016]萌萌哒

    建立ST表,每层维护一个并查集. 每个信息可以拆成两条长度为$2$的幂次的区间相等的信息,等价于ST表里两对点的合并. 然后递归合并,一旦发现已经合并过了就退出. 因为一共只会发生$O(n\log n ...

  8. 纯CSS打造银色MacBook Air(完整版)

    上一篇:<selection伪元素小解> ::selection{ background:blue; color:red; }p{font-size:14px;} 作者主页:myvin 博 ...

  9. [深入浅出Windows 10]不同平台设备的适配

    2.3 不同平台设备的适配 Windows 10通用应用程序针对特定的平台还会有一个子API的集合,当我们要使用到某个平台的特定API的时候(比如手机相机硬件按钮触发事件),这时候就需要调用特定平台的 ...

  10. git两种合并方法 比较merge和rebase

    18:01 2015/11/18git两种合并方法 比较merge和rebase其实很简单,就是合并后每个commit提交的id记录的顺序而已注意:重要的是如果公司用了grrit,grrit不允许用m ...