码迷,mamicode.com
首页 > 其他好文 > 详细

oc学习之路----QQ聊天界面

时间:2015-01-16 01:02:33      阅读:376      评论:0      收藏:0      [点我收藏+]

标签:

用到的技术:自定义cell,通知机制,代理模式 transform

  1.自定义cell(通过代码自定义cell)

    ①首先新建一个类继承UITableViewCell

    ②重写initWithStyle:reuseIdentifier方法

       这里只需要把所有要显示的子控件添加到contenView中,在这一步一般不需要设置属性的,       但是如果是一些子控件中一些静态的属性,字需要一次性设置的话,就在这里              设置,在重写frameSet方法的时候在把一些比较动态的数据填充上去以及设置

       每个子控件的frame

    ③提供两个模型

      数据模型:存放数据

      frame模型:通过拿到数据模型来计算每一个空间的frame,并设置为readOnly

  2.通知机制

    技术分享

由此可见,我们可以这样认为 ,在一个程序运行过程中,有很多控件向通知中心发送通知,而我们可以随时随地的接收想要的通知,这点类似于代理,但是区别于的代理的是,通知比代理灵活,而且通知是多对多关系,一个对象可以告诉N个对象发生什么事情,一个对象能得知N个对象发生什么事情,而代理是一对一关系,一个对象只能告诉一个对象发生什么事情。

    通知发布

      

- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
//发布一个名称为aName的通知,anObject为这个通知的发布者,aUserInfo为额外信息

 

    通知监听

通知中心提供方法来注册一个监听通知的监听器(换言之就是,将自定义通知公之于世)

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
/**
observer:监听器,即谁要接收这个通知
aSelector:收到通知后,回调监听器的这个方法,并且把通知对象当做参数传入
aName:通知的名称。如果为nil,那么无论通知的名称是什么,监听器都能收到这个通知
anObject:通知发布者。如果为anObject和aName都为nil,监听器都收到所有的通知*/

    取消注册监听器

      

/*
通知中心不会保留(retain)监听器对象,在通知中心注册过的对象,必须在该对象释放前取消注册。否则,当相应的通知再次出现时,通知中心仍然会向该监听器发送消息。因为相应的监听器对象已经被释放了,所以可能会导致应用崩溃

通知中心提供了相应的方法来取消注册监听器
*/
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;

//一般在监听器销毁之前取消注册(如在监听器中加入下列代码):
- (void)dealloc {
    //[super dealloc];  非ARC中需要调用此句
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

 

    通知监听

      

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];

  3 代理模式

    简单步骤就是:一个协议 一个返回实现该协议的id类型的delegate 还有就是 在使用短实现协议,并且实现协议的方法

  

难点:自定义cell,聊天图片的无变化拉伸,键盘的监听  

思路:新建模型一个计算位置的,一个填充数据的

   新建View.用于显示每一个cell里面的数据m   

细节:

  

/**
* 数据模型
* MessageDataModel.m
*/
@implementation MessageDataModel
+(instancetype)messageWithDict:(NSDictionary *)dict{
    return [[self alloc] initWithDict:dict];
}
-(instancetype)initWithDict:(NSDictionary *)dict{
    if(self = [super init]){
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}
@end
/**
* 位置模型
* MessageFrameData.m
*/
#define MJTextFont [UIFont systemFontOfSize:15]
#import "MessageFrameData.h"
#import "MessageDataModel.h"

@implementation MessageFrameData
-(void)setMessage:(MessageDataModel *)message {
    _message = message;
//    间距
    CGFloat padding = 10;
//    屏幕的宽度
    CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
    NSLog(@"==========%f",screenW);
//    时间布局
    if(!message.hideTime){
        CGFloat timeX = 0;
        CGFloat timeY = 0;
        CGFloat timeW = screenW;
        CGFloat timeH = 40;
        _timeF = CGRectMake(timeX, timeY, timeW, timeH);
    }


//    头像布局
    CGFloat iconY = CGRectGetMaxY(_timeF)+padding;
    CGFloat iconW = 40;
    CGFloat iconH = 40;
    CGFloat iconX;
    if(message.type == MessageTypeOther){//别人发的
        iconX = padding;
    } else{//自己发的
        iconX = screenW - padding -iconW;
    }
    _iconF = CGRectMake(iconX, iconY, iconW, iconH);

//    正文
    CGFloat textY = iconY;
//    能显示的最大size
    CGSize textMaxSize = CGSizeMake(150, MAXFLOAT);
//    文本的真实size
    CGSize textSize = [self sizeWithText:message.text font:MJTextFont maxSize:textMaxSize];
//    最终确定的size;
    CGSize textBtnSize = CGSizeMake(textSize.width+ TextPadding*2, textSize.height+ TextPadding*2);
    CGFloat textX;
    if(message.type == MessageTypeOther){
        textX = CGRectGetMaxX(_iconF)+padding;
    } else{
        textX = iconX - padding -textBtnSize.width;
    }
    _textF = (CGRect){{textX,textY},textBtnSize};
//    _textF = CGRectMake(textX, textY, textSize.width, textSize.height);

    CGFloat textMaxY = CGRectGetMaxY(_textF);
    CGFloat iconMaxY = CGRectGetMaxY(_iconF);
    _cellHeight = MAX(textMaxY, iconMaxY) + padding;
}
/**
*  计算文字尺寸
*
*  @param text    需要计算尺寸的文字
*  @param font    文字的字体
*  @param maxSize 文字的最大尺寸
*/
- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize
{
    NSDictionary *attrs = @{NSFontAttributeName : font};
    return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
}
@end
/**
* 自定义cell,用于填充数据和设置frame
*/
#define MJTextFont [UIFont systemFontOfSize:15]
#import "QQQViewCellTableViewCell.h"
#import "MessageDataModel.h"
#import "UIImage+Extension.h"

@interface QQQViewCellTableViewCell()
//内容
@property (nonatomic, weak) UIButton *textView;
//发送时间
@property (nonatomic, weak) UIImageView *iconView;
@property (nonatomic, weak)UILabel *timeView;
@end

@implementation QQQViewCellTableViewCell

/**
* 重写
*/
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
//        先调用父类方法
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self){
//        子空间的创建和初始化
//        时间
        UILabel *timeView = [[UILabel alloc] init];
        timeView.textAlignment = NSTextAlignmentCenter;
        timeView.textColor = [UIColor grayColor];
        timeView.font = [UIFont systemFontOfSize:13];
        [self.contentView addSubview:timeView];
        self.timeView = timeView;

//       头像
        UIImageView *iconView = [[UIImageView alloc] init];
        [self.contentView addSubview:iconView];
        self.iconView = iconView;

//        正文
        UIButton *textView = [[UIButton alloc] init];
        textView.titleLabel.numberOfLines = 0;
//        textView.backgroundColor = [UIColor grayColor];
        textView.titleLabel.font = MJTextFont;
        [textView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
//        设置内边距
        textView.contentEdgeInsets = UIEdgeInsetsMake(TextPadding, TextPadding, TextPadding, TextPadding);
        [self.contentView addSubview:textView];
        self.textView = textView;

//        设置cell的背景颜色
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

//这是布局
-(void)setModel:(MessageFrameData *)model {
    _model = model;
    MessageDataModel *message = model.message;
//    时间
    self.timeView.text = message.time;
    self.timeView.frame = model.timeF;
//    头像
    NSString *icon = (message.type == MessageTypeOther)?@"other":@"me";
    self.iconView.image = [UIImage imageNamed:icon];
    self.iconView.frame = model.iconF;
//    正文
    [self.textView setTitle:message.text forState:UIControlStateNormal];
    self.textView.frame = model.textF;
//    设置正文背景图
    if (message.type == MessageTypeMe){
        [self.textView setBackgroundImage:[UIImage resizableImage:@"chat_send_nor"] forState:UIControlStateNormal];
    } else{
        [self.textView setBackgroundImage:[UIImage resizableImage:@"chat_recive_nor"] forState:UIControlStateNormal];
    }
}


+(instancetype)cellWithTableView:(UITableView *)tableView{
    static NSString *ID = @"qqmessage";
    QQQViewCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if(cell == nil){
        cell = [[QQQViewCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

@end

 

oc学习之路----QQ聊天界面

标签:

原文地址:http://www.cnblogs.com/superYou/p/4227498.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!