tableViewCell自适应高度(QQ聊天室模拟)

先看一看效果吧!

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

废话不多说直接上代码

代码下载请猛戳这里

先看一看代码结构图:
这里写图片描述
MessageModel代码:

#import "MessageModel.h"

@implementation MessageModel
/**
 *  类方法创建一个消息模型实例
 *
 *  @param dic 描述模型的字典
 *
 *  @return 消息模型实例
 */
+ (instancetype)messageModelWithDictionary:(NSDictionary *)dic
{
    return [[self alloc] initWithDictionary:dic];
}
/**
 *  自定义初始化方法
 *
 *  @param dic 描述模型的字典
 *
 *  @return 消息模型实例
 */
- (instancetype)initWithDictionary:(NSDictionary *)dic
{
    if (self = [super init]) {
        if (dic) {
            [self setValuesForKeysWithDictionary:dic];
        }
    }

    return self;
}

@end

MessageFrameModel代码:

#import "MessageFrameModel.h"
#import "MainDefine.h"
#import "NSString+Extension.h"

@implementation MessageFrameModel

- (void)setIsHideTime:(BOOL)isHideTime
{
    _isHideTime = isHideTime;

    //设置计算出来的frame数据
    [self settingCalculationData];
}

/**
 *  类方法创建一个带有对应控件frame的消息模型实例
 *
 *  @param dic 描述模型的字典
 *
 *  @return 消息模型实例
 */
+ (instancetype)messageFrameModelWithDescription:(NSDictionary *)dic
{
    return [[self alloc] initWithDescription:dic];
}
/**
 *  自定义初始化方法
 *
 *  @param dic 描述模型的字典
 *
 *  @return 消息模型实例
 */
- (instancetype)initWithDescription:(NSDictionary *)dic
{
    if (self = [super initWithDictionary:dic]) {
        if (dic) {
            //设置计算出来的frame数据
            //[self settingCalculationData:dic];
        }
    }

    return self;
}

/**
 *  根据基础数据计算对应控件的frame
 *
 *  @param dic 基础数据字典
 */
- (void)settingCalculationData
{
    CGFloat spacing = 8.0;
    CGFloat timeX = 0.0;
    CGFloat timeY = 0.0;
    CGFloat timeHeight = 44.0;
    CGFloat iconWith = 50.0;

    if (!self.isHideTime) {
        self.timeFrame = CGRectMake(timeX, timeY, MAINSCREEM_WITH, timeHeight);
    }

    if (self.type == MessageTypeMySend)
    {
        self.iconFrame = CGRectMake(MAINSCREEM_WITH - spacing - iconWith, CGRectGetMaxY(self.timeFrame) + 8, iconWith, iconWith);
    }
    else
    {
        self.iconFrame = CGRectMake(spacing, CGRectGetMaxY(self.timeFrame) + spacing, iconWith, iconWith);
    }

    CGFloat targetWidth = MAINSCREEM_WITH - spacing - self.iconFrame.size.width*2 - TEXTBUTTON_PADDING*2;
    CGSize wordsS = [self.text autoSizeWithTargetWidth:targetWidth andFont:[UIFont systemFontOfSize:MEDIUM_FONT]];

    CGFloat textX = spacing + self.iconFrame.size.width;
    if (self.type == MessageTypeMySend) {
        textX = MAINSCREEM_WITH - textX - wordsS.width - TEXTBUTTON_PADDING*2;
    }
    self.textFrame = CGRectMake(textX, self.iconFrame.origin.y, wordsS.width + TEXTBUTTON_PADDING*2, wordsS.height + TEXTBUTTON_PADDING*2);

    self.cellHeight = MAX(CGRectGetMaxY(self.iconFrame), CGRectGetMaxY(self.textFrame));
}

MessageFrameModelList代码:

#import "MessageFrameModelList.h"
@interface MessageFrameModelList()
@property (strong, nonatomic)NSMutableArray *messageFrameModels;
@end

@implementation MessageFrameModelList
- (NSInteger)count
{
    return self.messageFrameModels.count;
}
/**
 *  类方法创建一个带有对应控件frame的消息模型列表实例
 *
 *  @param dic 描述模型列表的数组
 *
 *  @return 消息模型列表
 */
+ (instancetype)messageFrameModelListWithArray:(NSArray *)arr
{
    return [[self alloc] initWithArray:arr];
}
/**
 *  自定义初始化方法
 *
 *  @param dic 描述模型列表的数组
 *
 *  @return 消息模型列表
 */
- (instancetype)initWithArray:(NSArray *)arr
{
    if (self = [super init])
    {
        if (arr)
        {
            self.messageFrameModels = [NSMutableArray arrayWithCapacity:1];
            NSArray *messageArr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"messages" ofType:@"plist"]];

            for (int index = 0; index < messageArr.count; index++)
            {
                MessageFrameModel *messageFrameModel = [MessageFrameModel messageFrameModelWithDescription:messageArr[index]];

                MessageFrameModel *lastMessageFrameModel = [self.messageFrameModels lastObject];
                messageFrameModel.isHideTime = [messageFrameModel.time isEqual:lastMessageFrameModel.time];//如果和上一条消息时间相等,就隐藏时间

                [self.messageFrameModels addObject:messageFrameModel];
            }
        }
    }

    return self;
}

/**
 *  根据标号获取模型列表中的一个模型
 *
 *  @param index 标号
 *
 *  @return 带有对应控件frame的消息模型
 */
- (MessageFrameModel *)getMessageFrameModel:(NSInteger)index
{
    return self.messageFrameModels[index];
}

/**
 *  添加一条消息
 *
 *  @param messageDic 消息描述字典
 */
- (void)addMessageWithDictionary:(NSDictionary *)messageDic
{
    MessageFrameModel *messageFrameModel = [MessageFrameModel messageFrameModelWithDescription:messageDic];

    //设置是否隐藏时间
    MessageFrameModel *lastMessageFrameModel = [self.messageFrameModels lastObject];
    messageFrameModel.isHideTime = [messageFrameModel.time isEqualToString:lastMessageFrameModel.time];

    [self.messageFrameModels addObject:messageFrameModel];
}

@end

MessageCell代码:

#import "MessageCell.h"
#import "MainDefine.h"

@interface MessageCell()

/**
 *  时间
 */
@property (strong, nonatomic)UILabel *timeLabel;
/**
 *  头像
 */
@property (strong, nonatomic)UIImageView *iconImageView;
/**
 *  内容
 */
@property (strong, nonatomic)UIButton *textButton;

@end

@implementation MessageCell

/**
 *  类方法返回一个能重用的cell
 *
 *  @param tableView  使用此cell的tableView
 *  @param identifier 此类cell的重用标识符
 *
 *  @return 本cell的一个实例
 */
+ (instancetype)messageCell:(UITableView *)tableView
{
    static NSString *cellIdentifier = @"messageCell";
    MessageCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[MessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }

    return cell;
}

/**
 *  设置cell的内部控件大小
 *
 *  @param messageFrameModel 带对应控件大小的消息模型
 */
- (void)setMessageFrameModel:(MessageFrameModel *)messageFrameModel
{
    if (messageFrameModel) {
        _messageFrameModel = messageFrameModel;
        self.timeLabel.frame = messageFrameModel.timeFrame;
        self.timeLabel.text = messageFrameModel.time;
        self.timeLabel.hidden = messageFrameModel.isHideTime;

        self.iconImageView.frame = messageFrameModel.iconFrame;
        self.iconImageView.layer.cornerRadius = messageFrameModel.iconFrame.size.width/2;
        self.iconImageView.layer.masksToBounds = YES;
        self.iconImageView.image = [UIImage imageNamed:messageFrameModel.type == MessageTypeMySend ? @"me" : @"other"];

        self.textButton.frame = messageFrameModel.textFrame;
        [self.textButton setTitle:messageFrameModel.text forState:UIControlStateNormal];
        if (self.messageFrameModel.type == MessageTypeMySend)
        {
            [self.textButton setBackgroundImage:[self imageWithName:@"chat_send_nor"] forState:UIControlStateNormal];
            [self.textButton setBackgroundImage:[self imageWithName:@"chat_send_press_pic"] forState:UIControlStateHighlighted];
        }
        else
        {
            [self.textButton setBackgroundImage:[self imageWithName:@"chat_recive_nor"] forState:UIControlStateNormal];
            [self.textButton setBackgroundImage:[self imageWithName:@"chat_recive_press_pic"] forState:UIControlStateHighlighted];
        }
    }
}
/**
 *  不变形的拉伸图片
 *
 *  @param name 图片名称
 *
 *  @return 拉伸后的图片
 */
- (UIImage *)imageWithName:(NSString *)name
{
    UIImage *image = [UIImage imageNamed:name];
    CGFloat imageW = image.size.width/2;
    CGFloat imageH = image.size.height/2;
    return [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageH, imageW, imageH, imageW)];
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        self.timeLabel = [[UILabel alloc] init];
        self.timeLabel.textAlignment = NSTextAlignmentCenter;
        self.timeLabel.font = [UIFont systemFontOfSize:SMOLL_FONT];
        self.timeLabel.textColor = [UIColor grayColor];
        [self.contentView addSubview:self.timeLabel];

        self.iconImageView = [[UIImageView alloc] init];
        [self.contentView addSubview:self.iconImageView];

        self.textButton = [[UIButton alloc] init];
        [self.textButton setTitleEdgeInsets:UIEdgeInsetsMake(TEXTBUTTON_PADDING, TEXTBUTTON_PADDING, TEXTBUTTON_PADDING, TEXTBUTTON_PADDING)];
        self.textButton.titleLabel.font = [UIFont systemFontOfSize:MEDIUM_FONT];
        self.textButton.titleLabel.numberOfLines = 0;
        [self.textButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [self.contentView addSubview:self.textButton];

        [self setBackgroundColor:[UIColor clearColor]];
    }

    return self;
}

- (void)awakeFromNib {
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

ViewController代码:

#import "ViewController.h"
#import "MessageFrameModelList.h"
#import "MessageCell.h"

@interface ViewController ()<UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UITextField *textField;
/**
 *  带frame的消息数据模型表
 */
@property (strong, nonatomic)MessageFrameModelList *messageFrameModelList;

@end

@implementation ViewController
#pragma mark - 属性方法
- (MessageFrameModelList *)messageFrameModelList
{
    if (!_messageFrameModelList) {
        NSArray *arr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"messages" ofType:@"plist"]];
        _messageFrameModelList = [MessageFrameModelList messageFrameModelListWithArray:arr];

        //消息最开始滚到最后
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messageFrameModelList.count - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
    }

    return _messageFrameModelList;
}

#pragma mark - 控制器周期
- (void)viewDidLoad {
    [super viewDidLoad];

    //注册键盘通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];

    //设置文本框左边距
    self.textField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 4, 0)];
    self.textField.leftViewMode = UITextFieldViewModeAlways;

    //设置文本框代理
    self.textField.delegate = self;
}
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - 按钮手势事件
- (IBAction)didViewCtrClicked:(id)sender {
    [self.view endEditing:YES];
}
- (IBAction)didAddClicked:(UIButton *)sender {
    [self.view endEditing:YES];
}

#pragma 自定义方法
/*
 UIKeyboardAnimationCurveUserInfoKey = 7;  // 动画的执行节奏(速度)
 UIKeyboardAnimationDurationUserInfoKey = "0.25"; // 键盘弹出\隐藏动画所需要的时间
 UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";
 UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}";
 UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";
 UIKeyboardFrameChangedByUserInteraction = 0;

 // 键盘弹出
 UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";// 键盘刚出来那一刻的frame
 UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}"; //  键盘显示完毕后的frame

 // 键盘隐藏
 UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";
 UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";
 */
- (void)keyboardWillChangeFrame:(NSNotification *)notification
{
    //NSLog(@"%@",notification.userInfo);
    //self.view.frame = CGRectMake(self.view.frame.origin.x, [[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y - self.view.frame.size.height, self.view.frame.size.width, self.view.frame.size.height);
    //self.view.transform = CGAffineTransformTranslate(self.view.transform, 0, [[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y - [[notification.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].origin.y);

    //首尾式动画
    [UIView beginAnimations:nil context:nil];
    //设置动画时间
    [UIView setAnimationDuration:[[notification.userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    //设置动画节奏
    [UIView setAnimationCurve:[[notification.userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]];

    self.view.transform = CGAffineTransformMakeTranslation(0, [[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y - self.view.frame.size.height);

    [UIView commitAnimations];
}

- (void)addMessage:(NSString *)messageStr andType:(MessageType)messageType
{
    //设置时间
    NSDate *nowDate = [NSDate date];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSString *dateStr = [dateFormatter stringFromDate:nowDate];

    NSDictionary *messageDic = @{@"text":messageStr,@"type":[NSNumber numberWithInteger:messageType],@"time":dateStr};
    [self.messageFrameModelList addMessageWithDictionary:messageDic];

    //刷新tableView
    [self.tableView reloadData];
    //tableView滚动到最新消息处
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messageFrameModelList.count - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

/**
 *  根据自己发的内容取得自动回复的内容
 *
 *  @param text 自己发的内容
 */
- (NSString *)autoReply:(NSString *)textStr
{
    NSDictionary *repelyText = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"autoreply" ofType:@"plist"]];
    for (NSInteger i = 0; i < textStr.length; i++) {
        NSString *word = [textStr substringWithRange:NSMakeRange(i, 1)];
        if (repelyText[word]) {
            return repelyText[word];
        }
    }

    return @"你妹啊";
}

#pragma mark - UITableView代理
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.messageFrameModelList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MessageCell *cell = [MessageCell messageCell:tableView];
    cell.messageFrameModel = [self.messageFrameModelList getMessageFrameModel:indexPath.row];

    return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [self.messageFrameModelList getMessageFrameModel:indexPath.row].cellHeight;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

#pragma mark - UITextField代理
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [self addMessage:self.textField.text andType:MessageTypeMySend];

    //清空输入框
    self.textField.text = nil;

    //模拟回复
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSString *autoReplyText = [self autoReply:[self.messageFrameModelList getMessageFrameModel:self.messageFrameModelList.count - 1].text];
        [self addMessage:autoReplyText andType:MessageTypeOtherSend];
    });

    return YES;
}
@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值