1. 介绍QQ_聊天的基本功能
注意点:
* 下面文本框不是footerView,因为不会随着UITableView一起滚动
* 不能使用UITableViewController,因为UITableViewController中的view默认就是UITableView
* 实际做法:
1> 使用普通UIViewController,上面拽一个UITableView, 然后下面留出44高度
2> 底部放一个UIView,然后设置背景图,向其中添加子控件
* 为什么底部不用imageview,因为在xib或者storyboard中,直接拖控件无法成为imageview的子控件。通过代码可以。
* 小图片设置按钮的image属性,不要设置背景,会自动拉伸
* 设置聊天文本框的背景图片,为了保证在ios6,7下效果都一样
2. 搭建界面
3. 创建数据模型类(type使用枚举)、创建frame模型类
** 注意: frame 模型类不是根据字典来创建的, 所以无需为 frame 模型类封装 initWithDict: 方法。
/************************ 定义一个枚举****************************/
typedef enum {
SteveZMessageTypeMe = 1, // 表示自己发的消息
SteveZMessageTypeOther = 1 // 表示对方发的消息
} SteveZMessageType;
/************************ 定义一个枚举****************************/
定义枚举,利用程序阅读,降低沟通成本
4. 懒加载数据, 数组使用NSMutableArray, 因为聊天内容会不断增多
5. 设置UITableView的数据源对象, 实现3个数据源方法
6. 编写frame model(数据模型)的set方法, 在该方法中根据数据模型计算坐标
7. 编写自定义的Cell。重写initWithStyle方法, 在该方法中动态创建子控件
* 显示时间的Label、头像UIImageView、正文Label
8. 计算坐标
9. 封装"根据字符串"计算大小。封装到字符串的分类中。
10. 计算行高
11. 美化外观, 取消行与行之间的分割线
12._ 取消UITableView的行的选中高亮显示(tableView.allowsSelection= NO)
13. 设置tableView的背景色(236,236,236), 设置cell的背景色为clearColor
// 控制器中
self.tableView.backgroundColor = [UIColorcolorWithRed:236.0/255 green:236.0/255 blue:236.0/255 alpha:1.0];
// 自定义 Cell 中。
self.backgroundColor = [UIColor clearColor];
14. 在设置数据的时候, 根据时间间隔是否小于1分钟, 控制"时间Label"是否显示
* 关键如何获取上一条记录的"时间"
* 在数据模型中添加一个是否需要隐藏时间 Label 的属性(hideTime)
* 在懒加载的时候判断当前model和上一条(也就是模型数组中当前的最后一条)model的时间是否一致, 如果一致, 设置 hideTime = YES, 否则设置为 NO
** 注意: 虽然隐藏了"时间 Label", 但是在 frame模型中计算_iconY 的时候还是根据时间 Label 的最大的 Y 值来计算的, 所以要在 frame 模型中判断, 如果"时间 Label"被隐藏了, 那么就让 iconY = 0。(或者是, 如果不需要显示"时间 label", 那么就不需要计算"时间Label"的 frame 了。)
15. 设置正文的"背景图"
* 根据模型中数据的类型来设置背景图, 判断消息类型, 加载不同的图片
/** 参考代码:
// 设置正文的背景图片
NSString *nor,*highlighted;
if (message.type== CZMessageTypeMe) {
nor =@"chat_send_nor";
highlighted =@"chat_send_press_pic";
} else {
nor =@"chat_recive_nor";
highlighted =@"chat_recive_press_pic";
}
UIImage *imgNor =[UIImage imageNamed:nor];
UIImage*imgHighlighted = [UIImage imageNamed:highlighted];
[self.btnTextsetBackgroundImage:imgNor forState:UIControlStateNormal];
[self.btnTextsetBackgroundImage:imgHighlighted forState:UIControlStateHighlighted];
*/
16. 拉伸背景图片
* 采用平铺的方式拉伸
* 使用UIImage对象的stretchableImageWithLeftCapWidth:<#(NSInteger)#>topCapHeight:<#(NSInteger)#>方法来拉伸
* 设置按钮中titleLable距离按钮的内边距的距离
1> 按钮宽度加大40, 高度加高30
2> 设置titleLabel距离按钮的内边距(上15, 下15, 左20, 右20)
btnText.contentEdgeInsets = UIEdgeInsetsMake(15, 20, 15, 20);
17. 根据消息类型, 设置消息正文的文字颜色
18. 设置发消息的文本框的内容左边的空白
* 设置文本框的leftView属性, 添加一个新的UIView设置宽为10, 高为1
* 设置leftViewMode属性为always
19. 实现键盘的弹出效果
* 当键盘弹出的时候写代码
* 通过通知中心来监听键盘弹出事件
* 监听事件的3中方式:
1> addTarget,只有继承自UIControl的控件才能通过addTarget的方式来监听事件
2> 代理
3> 通过通知中心
20.通知中心
1. 一个完整的通知一般包含3个属性:
Ø - (NSString *)name; // 通知的名称
Ø - (id)object; // 通知发布者(是谁要发布通知)
Ø - (NSDictionary *)userInfo; // 一些额外的信息(通知发布者传递给通知接收者的信息内容)
我们一般使用这个方法初始化一个通知对象:
Ø -(instancetype)initWithName:(NSString *)name object:(id)objectuserInfo:(NSDictionary *)userInfo;
2.发布通知,我们一般使用这个方法:(一共有三种,最后一种结合了创建通知)
- (void)postNotificationName:(NSString *)aNameobject:(id)anObject userInfo:(NSDictionary *)aUserInfo;
Ø 发布一个名称为aName的通知,anObject为这个通知的发布者,aUserInfo为额外信息
3. // 获取通知中心
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
4. - (void)addObserver:(id)observerselector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
observer:监听器,即谁要接收这个通知
aSelector:收到通知后,回调监听器的这个方法,并且把通知对象当做参数传入
aName:通知的名称。如果为nil,那么无论通知的名称是什么,监听器都能收到这个通知
anObject:通知发布者。如果为anObject和aName都为nil,监听器都收到所有的通知
5.一般在对象销毁之前取消注册(如在监听器中加入下列代码):
- (void)dealloc {
//[super dealloc]; 非ARC中需要调用此句
[[NSNotificationCenter defaultCenter] removeObserver:self];
21. 监听键盘的弹出事件
* 在控制器的viewDidLoad方法中让控制器监听键盘的UIKeyboardWillChangeFrameNotification通知
- 谁发的这个通知并不重要, 所以可以传递nil
* 滚动到最后一行(滚动到最后)
NSIndexPath *idxPath = [NSIndexPath indexPathForRow:self.messages.count - 1 inSection:0];
[self.tableViewscrollToRowAtIndexPath:idxPath atScrollPosition:UITableViewScrollPositionTopanimated:YES];
* 在控制器的dealloc中移除监听
22.在UITableView的-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView事件中让键盘收回去
23. 把弹出键盘中的return键变成send键
* 选中文本框, 设置Return Key 属性的值为send
24. 监听Return Key的点击事件
1> 设置文本框的代理
2> 实现- (BOOL)textFieldShouldReturn:(UITextField*)textField方法。
* 在该方法中实现发送消息功能:
1》 获取文本框的输入
2》 新建数据模型、frame模型
3》 将frame模型添加到模型数组中
4》 刷新tableView
5》 将tableView滚动到最后一行
25. 封装一个sendMessage:(NSString *)msg type:(HMMessageType)type方法, 实现自动回复功能
26. iOS 9 开始键盘通知可以在多个app之间共享