您的位置:首页 > 其它

imitate wechat - 3

2015-09-07 21:14 183 查看
重新更新一篇可以说整个工程聊天界面最重要的一part,聊天列表的实现,这里我采用循序渐进的方法来完成学习,我先用setFrame的方法来实现,虽然setFrame方法复杂,但是对整体理解的要求更加高,更能理解面相对象的很多特性,例如封装、类的抽象化、对象消息传参等等重要的知识点。而setFrame的实现也是先实现纯文本的对话形式,当保证文本可以正常无bug的实现后再开枝散叶式地添加语音、图像、视频、表情等等等。而且setFrame的方法必须上网参考别人的起码三种实现,因为不同的代码风格和有一些实现技巧都可以对比对比,并且取其精华去其糟粕。当setFrame可以很好地实现,那么就开始尝试masonry的实现!

纯文本下setFrame方法:

先来看看实现一:

实现的类结构:





Model层的实现:

一:

ChartMessage.h

typedef enum
{
    kMessageFrom = 0,
    kMessageTo
    
} ChartMessageType;

#import <Foundation/Foundation.h>

@interface ChartMessage : NSObject

@property (nonatomic, assign) ChartMessageType messageType;//是消息的发送者还是接收者
@property (nonatomic, copy) NSString* icon;//icon是头像对应UIImage
@property (nonatomic, copy) NSString* content;//内容
@property (nonatomic, copy) NSDictionary* dict;//dic 装的是什么?

@end


ChartMessage.m

#import "ChartMessage.h"

@implementation ChartMessage

//这里可以开始掌握一种写法,在set方法里面设置数据变量
- (void)setDict:(NSDictionary *)dict
{
    _dict = dict;
    
    self.icon = dict[@"icon"];
    self.content = dict[@"content"];
    self.messageType = [dict[@"type"] intValue];
}

@end


二:

ChartCellFrame.h

#import "ChartMessage.h"
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@interface ChartCellFrame : NSObject

@property (nonatomic, assign) CGRect iconRect;              //图标的Rect值
@property (nonatomic, assign) CGRect chartViewRect;         //聊天内容的Rect值
@property (nonatomic, strong) ChartMessage* chartMessage;   //聊天内容
@property (nonatomic, assign) CGFloat cellHeight;           //整体的高度

@end


ChartCellFrame.m

#import "QQChating.h"
#import "ChartCellFrame.h"

@implementation ChartCellFrame

- (void)setChartMessage:(ChartMessage *)chartMessage
{
    _chartMessage = chartMessage;
    
    CGSize winSize = [UIScreen mainScreen].bounds.size;
    
    CGFloat iconX = kIconMarginX;
    CGFloat iconY = kIconMarginY;
    
    CGFloat iconWidth  = 40;
    CGFloat iconHeight = 40;
    
    if (chartMessage.messageType == kMessageFrom)
    {
        
    }
    else if (chartMessage.messageType == kMessageTo)
    {
        iconX = winSize.width - kIconMarginX - iconWidth;
    }
    
    self.iconRect = CGRectMake(iconX, iconY, iconWidth, iconHeight);
    
    CGFloat contentX = CGRectGetMaxX(self.iconRect) + kIconMarginX;
    
    CGFloat contentY = iconY;
    
    //这里为什么是写死200
    NSDictionary* attributes = @{NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue" size:13]};
    
    CGSize contentSize = [chartMessage.content boundingRectWithSize:CGSizeMake(200, MAXFLOAT)
                                                            options:NSStringDrawingTruncatesLastVisibleLine |
                                                                    NSStringDrawingUsesLineFragmentOrigin |
                                                                    NSStringDrawingUsesFontLeading
                                                                    attributes:attributes
                                                                    context:nil].size;
    if (chartMessage.messageType == kMessageTo)
    {
        contentX = iconX - kIconMarginX - contentSize.width - iconWidth;
    }
    
    self.chartViewRect = CGRectMake(contentX, contentY,
                                    contentSize.width + 35,
                                    contentSize.height + 30);
    
    self.cellHeight = MAX(CGRectGetMaxY(self.iconRect), CGRectGetMaxY(self.chartViewRect)) + kIconMarginY;
}

@end


View层的实现:

一:

ChartContentViewDelegate.h

#import <Foundation/Foundation.h>
@class ChartContentView, ChartMessage;

@protocol ChartContentViewDelegate <NSObject>

//定义一个委托类,越来越觉得委托的作用和接口一样了。
//如何定义参数上都是一门学问,例如可以传的东西有,self自身(self这种东西很有用的)
//这个时候就要第一个参数的类是self类,同时另外的参数可以根据需求来
- (void)chartContentViewLongPress:(ChartContentView *)chartView content:(NSString *)content;
- (void)chartContentViewTapPress:(ChartContentView *)chartView content:(NSString *)content;

@end


二:

ChartContentView.h

#import "QQChating.h"
#import <UIKit/UIKit.h>
#import "ChartMessage.h"
#import "ChartContentViewDelegate.h"

@interface ChartContentView : UIView

@property (nonatomic, strong)UILabel* contentLabel;
@property (nonatomic, strong)ChartMessage* chartMessage;
@property (nonatomic, strong)UIImageView* backImageView;
@property (nonatomic, strong)id<ChartContentViewDelegate> delegate;

@end


ChartContentView.m

#import "ChartContentView.h"

@implementation ChartContentView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    
    if (self)
    {
        self.backImageView = [[UIImageView alloc] init];
        self.backImageView.userInteractionEnabled = YES;
        [self addSubview:self.backImageView];
        
        self.contentLabel = [[UILabel alloc] init];
        self.contentLabel.numberOfLines = 0;
        self.contentLabel.textAlignment = NSTextAlignmentLeft;
        self.contentLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:13];
        [self addSubview:self.contentLabel];
        
        [self addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longTap:)]];
        [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapPress:)]];
    }
    
    return self;
}

- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    
    self.backImageView.frame = self.bounds;
    
    CGFloat contentLabelX = 0;
    
    if (self.chartMessage.messageType == kMessageFrom)
    {
        contentLabelX = kContentStartMargin*0.8;
    }
    else if (self.chartMessage.messageType == kMessageTo)
    {
        contentLabelX = kContentStartMargin*0.5;
    }
    
    self.contentLabel.frame = CGRectMake(contentLabelX, -3,
                                         self.frame.size.width-kContentStartMargin-5, self.frame.size.height);
}

/**
 *  表面上是一个普通的手势,其实内涵乾坤
 *  这里的乾坤就是表面上是contentView的长按操作
 *  其实就是为了委托方法的实现
 *  就相当于textField输入框的代理方法里面,你一输入,调用的却是self.delegate的执行代理方法
 */
- (void)longTap:(UILongPressGestureRecognizer *)longTap
{
    if ([self.delegate respondsToSelector:@selector(chartContentViewLongPress:content:)])
    {
        [self.delegate chartContentViewLongPress:self content:self.contentLabel.text];
    }
}

- (void)tapPress:(UILongPressGestureRecognizer *)tapPress
{
    if ([self.delegate respondsToSelector:@selector(chartContentViewTapPress:content:)])
    {
        [self.delegate chartContentViewTapPress:self content:self.contentLabel.text];
    }
}

@end


接下篇!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: