一、知识点:

  QQ聊天界面

  双模型的使用(dataModel和frameModel)

  UITextField的使用

  通知的使用

  拉伸图片的两种方法(slicing/image对象的resizeableImageWithCapInsets属性)

  枚举

  方法的抽取(相同的拿出,不同的部分作为参数)

二、设置tableview的基本格式

1)定义tableview基本

numberOfSectionsInTableView:设置块

numberOfRowsInSection:设置每块对应的行数

cellForRowAtIndexPath:设置cell样式

2)cell的重用

  设置cell

satic NSString *identifier =@"QQCell";

  先从缓存池中寻找

QQCell *cell =[_tableview dequeuesableCellWithIdentifier:identifier];

  如果缓存池中找不到cell 就创建

if(cell==nil)

{cell =[[QQCell alloc]initWithStyle:UITableViewCellStyleDefault reuserIndentiier:identifier];}

3)设定自定义的cell格式(注意为什么消息框是button:因为既可以设置文本,又可以设置图片)

a、定义需要用到的属性及样式

@property(nonatomic,weak)UILabel *timeLabel;

@property(nonatomic,weak)UIButton *textButton;

@property(nonatomic,weak)UIImageView *iconImage;

b、定义初始化方法,注意与viewController中cell创建时调用的方法要一致

-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{

if(self =[super initWithStyle:style reuseIdentifier:reuseIdentifier]{

[self setupUI];//在内部设置button、label之类的样式

}}return self;

c、双模型(在懒加载中将数据模型传递给frame模型:原因:
  1、懒加载中,方法只需要执行一次

  2、行高rowheight 方法必须在cell方法调用前调用,所以要在cell中实现frame的计算,传递出来顺序是有问题的

传递方式: 在frameModel中定义QQModel这一属性

  a、定义model属性

  @class QQModel;

  @property (nonatomic ,strong) QQModel *qqModel;

  b、在懒加载中实现赋值

  QQModel *model =[QQModel QQmodelWithDictionary:dict];

  QQFrameModel *frameModel =[QQFrameModel alloc]init];

  frameModel.qqModel =model;//传递成功

  c、把frameModel的值传入dataArray数组中,因为这会frameModel中既有(数据model也包含各个控件的Frame)

  [_dataArray addObject:frameModel];

d、如何根据文本数据内容,设置frame

  1)、设置最大可变动区域(如果无限制则:MAXFLOAT)

  CGSize maxArea =CGSizeMake(textMaxA,MAXFLOAT);

  2)、设置属性字典(注意属性字体大小的设置一定要和原先控件中字体大小一致,否则,可能文本中以省略号带过)

  NSDictionary *dict =@{NSFontAttributeName:[UIFont systemFontOfSize:17};

  3)、设置对象数据的真实大小boundingRectWithSize

  CGSize RealSize =[_qqModel.text boundingRectWithSize :maxArea options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context :nil].size;

  

e、在cell的设置类中调用frameModel和数据模型并设置

  1)重写FrameModel的set方法:

@property(nonatomic,strong) QQFrameModel *frameModel;

-(void)setFrameModel:(QQFrameModel *)frameModel{

  2)必须对模型进行实例化

_frameModel =frameModel;

  3)设置模型中的数据和Frame

}

  怎么获取qqModel

  #import “QQModel.h”

  QQModel *qqModel =_frameModel.qqModel;

f、代码实现图片拉伸

/**

1、获取图片

2、设置拉伸 线条构成的中心区域(区域越小越好,所以将宽高都设成其中心线)

3、调用image对象的resizableImageWithCapInSets属性

*/

UIImage *image =[UIImage imageNamed:imageName];

CGFloat *halfWidth =image.size.width/2;

CGFloat *halfHeight =image.size.height/2;

UIImage *resizeImage =[image resizableImageWithCapInsets:UIEdgeInsetsMake(halfHeight,halfWidth,halfHeight,halfWidth) resizingMode:UIImageResizingModeStretch];

g、注意图片拉伸之后,文本可能不在图片内部,可以通过增加button的frame大小,同时设置文本的那边距(contentEdgeInsets UIEdgeInsetsMake)

textButton.contentEdgeInsets =UIEdgeInsetsMake(20,20,20,20);

h、设置行高

heightForRowAtIndexPath

QQ FrameModel *frameModel =self.dataArray[indexPath.row];

return frameModel.cellHeight

三、比较时间(两两比较,同一时间内的label只显示一遍,可以知道,只要比较一次,而且又要获得上一次的时间,最好在懒加载中实现)

/**

0、在qqModel中设置一个HiddenTimeLabel属性 存储比较完的结果

1、取出上一次的数据

2、进行比较,如果一样的话,就往qqModel 中传入HiddenTimeLabel=YES

*/

@property (nonatomic,assign,getter = isHiddenTimeLabel) BOOL HiddenTimeLabel;

QQFrameModel *latFrameModel =self.dataArray.lastObject;

if([lastFrameModel.qqModel.time isEqualToString :frameModel.qqModel.time])

{

qqModel.HiddenTimeLabel=YES;

}

调用:

_timeLabel.hidden =qqModel.isHiddenTimeLabel;(在hidden属性中直接调用重写的get方法即可)

四、补充使用枚举(内部的值类别,枚举的值名称,默认从0开始)

typedef NS_ENUM(NSInteger,QQUserType)

{

QQUserTypeOther=0;

QQuserTypeMe,

};

枚举的好处:将无意义的数字转化成有意义的字符,增加代码可读性

五、设置底部的弹框(了解textField属性和通知概念)

五.1 TextField 的使用

textField.placeholder=@"占位符"

 UIView *left =[[UIView alloc]initWithFrame:CGRectMake(100, 0, 10, 10)];

left.backgroundColor=[UIColor orangeColor];

text.leftView=left;

text.leftViewMode = UITextFieldViewModeAlways;

(添加leftview的时候必须要设置UITextFieldViewMode否则无法显示

leftview/rightview/leftViewMode/rightViewMode

密码:
text.secureTextEntry=YES;

text.cleanButtonMode =UITextFieldViewModeWhileEditing;

五、2)通知的使用

/**

1、注册监听者

2、通知中心发布通知

3、将销毁的监听者移除监听

*/

1

/**

addObserver: 监听对象

selector:监听对象收到通知之后调用的方法

name:通知的名称

object: 通知的发布者

*/

[[NSNotificationCenter defaultCenter] addObserver:ZhangSan selector:@selector(recieveNotification:) name:@"HuoYing" object:souhuHuoYing];

2

/**

接受通知之后,要执行的方法

*/

-(void) recieveNotification:(NSNotification *)noti

{

NSDictionary *c = noti.userInfo;

Company *company = c[@"company"];

NSLog(@"%@ 订阅了 %@公司的 %@视频已经更新了",self.personname,company.companyname,company.moviename);

//  NSLog(@"%@",noti);

}

3

-(void) dealloc

{

[[NSNotificationCenter defaultCenter]removeObserver:self.personname];

}

五、3)设置键盘监听,通过监听传递出的通知,改变底部输入框的frame和tableview的frame

1、// 添加监听,  键盘即将隐藏的时候, 调用

[[NSNotificationCenter defaultCenter] addObserver:self

selector:@selector(keyboardWillDisAppear:)

name:UIKeyboardWillHideNotification

object:nil];

调用的监听通知名称包括:UIKeyboardWillHideNotification /键盘即将隐藏的通知名

name:UIKeyboardWillChangeFrameNotification/键盘隐藏或出现的通知名

UIKeyboardWillShowNotification/键盘出现的通知名

2、收到通知消息时要执行的动画:(UIView animateWithDuration)

[UIView animateWithDuration:interval animations:^{

self.view.transform = CGAffineTransformMakeTranslation(0, (keyboardEndY - keyboardBeginY));

}];

3、用户如果滚动tableview的时候,或者用户输入完成按return的时候,键盘都需要消失

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

// 撤销textField 的第一响应者身份

[_textField resignFirstResponder];

}

4、默认的时候,tableview都应该滚动到最后一行(UITableView scrollToRowAtIndexPath)

- (void)scrollToBottom {

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.dataArray.count - 1 inSection:0];

[_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

}

5、既然是聊天框,那么cell就不应该有被选中时候的颜色(selectionStyle)

// 选中cell后不改变颜色

cell.selectionStyle = UITableViewCellSelectionStyleNone;

6、撤销监听

#warning 一定不要忘记移除监听者

- (void)dealloc {

[[NSNotificationCenter defaultCenter] removeObserver:self];

}

六、设置时间格式

/**

1、取出时间(NSDate date)

2、初始化格式NSDateFormatter (NASDateFormatter) formatter.dateformat(属性)

3、日期转字符 formatter stringFromDate:currentDate

*/

// 取出当前的时间

NSDate *currentDate = [NSDate date];

// 设置时间的格式

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

// 时间格式

// yyyy-MM-dd HH:mm:ss  时间格式

formatter.dateFormat = @"HH:mm";

NSString *dateString = [formatter stringFromDate:currentDate];

七、通知和代理的区别

共同:都可以传递消息

区别:代理是一对一传递,通知是多对多,可以有多个消息发布者和多个消息接收者

例如,代理可以知道textfiled什么时候开始输入值,什么时候结束输入值,但是像键盘这种弹入弹出它的时间都是不可控的,需要实时监测这个就需要通知中心发布消息。

Objective-c——UI基础开发第八天(QQ聊天界面)的更多相关文章

  1. WPF开发实例——仿QQ登录界面

    原文:WPF开发实例--仿QQ登录界面 版权声明:本文为博主原创文章,如需转载请标明转载地址 http://blog.csdn.net/u013981858 https://blog.csdn.net ...

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

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

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

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

  4. 高仿qq聊天界面

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

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

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

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

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

  7. WPF和Expression Blend开发实例:模拟QQ登陆界面打开和关闭特效

    不管在消费者的心中腾讯是一个怎么样的模仿者抄袭者的形象,但是腾讯在软件交互上的设计一直是一流的.正如某位已故的知名产品经理所说的:设计并非外观怎样,感觉如何.设计的是产品的工作原理.我觉得腾讯掌握了其 ...

  8. Android 根据QQ号跳转到QQ聊天界面

    从自己开发的应用中根据QQ号跳转到QQ应用的聊天界面,实现起来很方便: 即: startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(" ...

  9. Android—简单的仿QQ聊天界面

    最近仿照QQ聊天做了一个类似界面,先看下界面组成(画面不太美凑合凑合呗,,,,):

随机推荐

  1. POJ 3207 2-sat

    题目大意: 在圆上顺时针n个点,给定m个连接,可以通过圆内或者圆外相交,问能不能找到一种方式,使这些连接的边都不相交 这里很容易看出的是,这些边只有在圆外或者圆内两种连接方式,而且必须选择其中一种 所 ...

  2. K2与OData和Swagger集成,从任何设备无需代码获取数据

    K2近期宣布获得了DData和Swagger REST的支持,这件事情究竟有多好呢? K2与OData和Swagger的集成,保障K2 Blackpearl的用户能建立基于工作流和表单的解决方案,最重 ...

  3. [转]ps/2键盘线序识别方法

    from: http://www.360doc.com/content/11/0816/19/844619_140875056.shtml 经常看到有人询问ps/2线坏了,更换的时候如何测线序连线,或 ...

  4. switch… case 语句的用法(一)

    public class Test7 { public static void main(String[] args) { int i=5; switch(i) { case 1: System.ou ...

  5. 微软发布Windows Phone 8.1 Update 和中文版Cortana“小娜”

    Windows Phone 8.1 尚在推送进程中,它的第一个 GDR 更新就发布了.今天微软正式发布 Windows Phone 8.1 Update 和中文版 Cortana ——“小娜”. Wi ...

  6. goldengate复制过程字符集处理一例

    源端是oracle, al32utf8,表里有乱码,目标端是sybase cp936,两端的DB都不能改字符集,而且源端是目标端的超集,当复制有乱码的数据(非中文或英文数字等),目标端replicat ...

  7. IOS UTF8中文字母数字 组合时长度截取

    //计算总共字数和限制字数的Index位置 -(NSMutableArray *) unicodeLengthOfString: (NSString *) text { NSMutableArray ...

  8. JVM值内存垃圾回收监控之jstat

    如何判断JVM垃圾回收是否正常?一般的top指令基本上满足不了这样的需求,因为top主要监控的是总体的系统资源,很难定位到java应用程序. Jstat是JDK自带的一个轻量级小工具.全称“Java ...

  9. Android IPC(inter-process Communitcation)

    Android IPC(inter-process Communitcation) http://www.cnblogs.com/imlucky/archive/2013/08/08/3246013. ...

  10. Apache与Nginx的区分比较

    什么是Nginx代理代理服务器,它和Apache相比又有什么区别呢?你又该如何选择使用呢,用其中一个还是两者都用?我们将会在这里探索一下这些问题的答案. Apache服务器从1995年就开始使用了.相 ...